Tải bản đầy đủ (.ppt) (42 trang)

Thuật toán sinh và quay lui

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (423.16 KB, 42 trang )

ÔN TẬP KTLT 2
Thuật toán sinh và quay lui

1


Dàn bài
1.

Thuật toán sinh và bài tập

2.

Thuật toán quay lui và bài tập

2


Bài toán sinh
1.
2.
3.
(1)

Định nghĩa: Tạo ra dữ liệu.
Phương pháp sinh: Từ dữ liệu ban đầu, sinh ra dữ
liệu kế tiếp cho đến khi kết thúc.
Điều kiện của thuật toán sinh:
Có thể xác định 1 thứ tự tập các cấu hình của tổ hợp
(thứ tự của các phép gán trị, thường dùng thứ tự từ
điển).


Ví dụ: S1=“1234589”, S2=“1235789”
S1 < S2 nếu có 1 vị trí i tại đó S1[ i ] < S2[ i ]

(2) Có một cấu hình cuối (điều kiện kết thúc của thuật
toán).
(3) Có một cách để suy ra được cấu hình kế tiếp.
4. Áp dụng: giải bài toán liệt kê
3



dụ
Bài toán:Tìm số chuỗi có
độ dài 3 ký tự xyz với
x ∈ { a,b,c}, y ∈ { d,e},
z ∈ { m,n,t}
Cấu hình ban đầu: trị đầu
tiên của mỗi miền trị
Cách sinh:Lấy trị kết tiếp của
mỗi miền trị theo cơ chế
vòng tròn
Cấu hình cuối: trị cuối cùng
của mỗi miền trị

x
a
a
a
a
a

a
b
b
b
b
b
b
c
c
c
c
c
c

y
d
d
d
e
e
e
d
d
d
e
e
e
d
d
d

e
e
e

z
m
n
t
m
n
t
m
n
t
m
n
t
m
n
t
m
n
t

Dùng thứ
tự từ điển
để so sánh
các phép
gán trị.
Ví dụ:

adm < adn

4


Thuật toán sinh tổng quát.
Generate()
{
c = InitialConfigure(); //cấu hình ban đầu
Process (c);
// xử lý cấu hình đang có
if (c=LastConfigure()) Stop=true
else stop = false;
while (not stop)
{
//Sinh cấu hình kế tiếp từ cấu hình đang có

c=getNextConfigure(c);
Process (c); // xử lý cấu hình này
if c= LastConfigure then stop = true;

}
End;

5


Bài toán liệt kê các tập con của 1 tập



Với tập cha là 4 phần tử X={ a, b, c, d }, có thể dùng
mảng “0111” mô tả cho tập con { b,c,d }.

 Mỗi tập con được biểu diễn là một chuỗi (xâu) nhị
phân.



Trạng thái khởi tạo: “0000” mang ý nghĩa tập trống.
Trạng thái kết thúc: “1111” mang ý nghĩa là tập cha.

6



dụ
:
liệt

các
tập
con....
4


Với tập cha gồm 4 phần tử, có 2 tập con b
với các biểu diễn:

bits
0000

0001
0010
0011
0100
0101
0110
0111

p(b)
0
1
2
3
4
5
6
7

bits
1000
1001
1010
1011
1100
1101
1110
1111

p(b)
8

9
10
11
12
13
14
15

Nhận xét
Với thứ tự từ điển, tập con sau lớn
hơn tập con trước 1 đơn vị
theo cách tính chuỗi nhị phân

7


Đặt tả thuật toán sinh


Cách cộng thêm 1 vào chuỗi nhị phân:

0000

0001

0001

0010

0011


0100

0111

1000

• Gọi i : vị trí bit 0 đầu tiên từ
bên phải.
• Cho các bit 1 bên phải vị trí i
thành 0
•Cho bit i mang trị 1
i= n-1;
while (i>=0 && bits[i]==1) bits[i--] = 0;
bits[i] = 1;
8


Viết chương trình liệt kê
p(b)
void InitConfigure(char bits[], int n) bits
0123_____
{ for (int i=0; i}
0000
0
p(b)
void NextConfigure(char bits[], int n) bits
0123_____
{ int i = n-1;


while(i>=0 && bits[i])
{ bits[i]=0;
i--;
}
bits[i]=1;
}
int LastConfigure(char bits[], int n)
{ for (int i=0; ireturn 0;
return 1;
}

0000
0001
0010
0011
0100
0101
0110
0111

0
1
2
3
4
5
6
7


bits
p(b)
0123_____
1111

15
9


Viết chương trình liệt kê
void Output(char bits[], int n, int count)
{ printf( ‘’\nTap con thu %d\t’’,count);
for (int i=0; i}

void Generate(char bits[], int n)
{ int stop= FALSE;
InitialConfigure(bits, n); //cấu hình ban đầu
int count=1;
Output(bits,n,count) // xuat cấu hình đang có
while (!stop)
{ //Sinh cấu hình kế tiếp từ cấu hình đang có
NextConfigure(bits, n);
count++
Output(bits,n,count); //xuat cấu hình này
stop= LastConfigure(bits,n) ;
}
}
10



Cải tiến thuật toán liệt kê các tập con
Nhận xét: Có thể tối ưu lại chương trình.
void NextConfigure(char bits[], int n,
int &Stop)
{ int i = n-1;
while(i>=0 && bits[i])
{ bits[i]=0;
i--;
}
if (i <0) Stop=TRUE; // mọi bit = 1
else bits[i]=1;
}

void Generate(char bits[], int n)
{ int stop= FALSE;
InitialConfigure(bits, n); //cấu hình ban đầu
int count=1;
Output(bits,n,count) // xuat cấu hình đang có
while (!stop)
{
//Sinh cấu hình kế tiếp từ cấu hình đang có
c=NextConfigure(bits, n, stop);
if (!stop)
{ count++;
Output(bits,n,count); //xuat cấu hình này
}
}
}


11


Bài toán tập con k-phần tử : Tìm hiều
Liệt kê các tập con k phần tử của tập n phần tử.
 Ví dụ: Các tập con 3 phần tử của tập 5 phần tử
{ 1,2,3,4,5 } là:
C53 = 5!/ (3! * (5-3)!)
{ 1,2,3 } { 2,3,4 }
= 5! / (3! * 2!)
{ 1,2,4 } { 2,3,5 }
= 4*5/2 = 10
{ 1,2,5 } { 2,4,5 }
{ 1,3,4 } { 3,4,5 }
{ 1,3,5 }
Tổ hợp n chập k
{ 1,4,5 }


12


Bài toán tập con k-phần tử: Đặc tả



Ánh xạ tập hợp bất kỳ n phần tử vào tập X={ 1,2...n }
Một tập con k phần tử của X là một bộ có thứ tự a 1
a2 a3 ..... ak với 1≤ a1< a2 < a3 <..... < ak ≤ n


Tập con đầu: { 1,2,3,...,k }
Ví dụ { 1,2,3 } với k=3, n=5
 Tập con cuối:{ (n-k+1), (n-k+2) , ..., n }
Ví dụ: { 3,4,5 } với k=3, n=5


13


Thuật toán sinh tập con kế tiếp từ tập con đã có
a1 a2 a3 a4 ...ak , chỉ số ở đây đi từ 1
(1) Tìm vị trí đầu tiên từ bên
phải 1 vị trí i sao cho a[i]
≠ n-k+i
i=k;
while (a[i]==n-k+i) i-- ;
(2) Thay a[i] bằng a[i] +1
a[i]= a[i] + 1;
(3) Thay các trị sau i (a[j])
bằng các trị a[i]+j-i ,...
for (j=i+1;j<=k;j++)
a[j]= a[i]+ j -i;

n=8, k=6
{ 1,2,5,6,7,8 }
(i=6, n-k+i =8)
{ 1,3,5,6,7,8 }

{ 1,3,4,5,6,7 }


14

Tìm vị trí
đầu tiên
khác với
nhóm trị ở
cuối tập
cha theo
thứ tự


Viết chương trình bài toán tập con k- phần tử (1)
void Init (int result[], int k)
{ for (int i=1; i<=k; i++) result[i]=i;
}

{ 1,2,3 }

void Process (int result[], int k)
{ printf(‘’\n’’);
for (int i=1; i<=k; i++) printf(‘’%d,’’, result[i]);
}

void NextCombination (int result[],int n, int k, int &stop)
{ int i=k;
while(i>0 && result[i]==n-k+i) i--;
if (i>0)
{ result[i]++;
for (int j=i+1; j<=k; j++)

result[j]=result[i] + j-i;
}
else stop=1;
}

{ 1,2,4 }
{ 1,2,5 }


{ 3,4,5 }
15


Viết chương trình bài toán tập con k- phần tử (2)
void Generate(int result[], int n, int k)
{ int stop= FALSE;
Init(result, k); //cấu hình ban đầu
Process(result,k) // xuat cấu hình khoi dau
while (!stop)
{
//Sinh cấu hình kế tiếp từ cấu hình đang có
NextCombination(result, n,k, stop);
if (!stop)
Process(result, k); //xuat cấu hình này
}
}

16



Bài tập


Tạo tập tin văn bản có tên Tapcon.in chứa nội dung : 10 4



Ý nghĩa: số đầu: số phần tử của tập, số kế tiếp là số phần tử
của tập con.



Dùng kỹ thuật sinh, viết chương trình ghi các tập con của tập
này lên file Tapcon.out

17


Bài toán hoán vị tập n phần tử
Cho tập X = { 1,2,3,..., n}. Hãy liệt kê tất cả các hoán vị
của tập này.
 Một hoán vị của X là một bộ A = (a1, a2,..., an ) với ai ≠
aj nếu i ≠ j
 Định nghĩa 1 thứ tự:
A = (a1, a2,...,ak-1, ak, ... an ) là hoán vị trước của
A’= (a’1, a’2,...,a’k-1, a’k, ... a’n ) nếu tìm được vị trí k sao
cho ak < a’k
 Ví dụ : 1234567 là hoán vị trước của
1234657
 Đây chính là thứ tự từ điển.

 Độ phức tạp n!

18


Thuật toán sinh hoán vị kế tiếp
Trạng thái đầu {1,2,3,4} trạng thái cuối: {4,3,2,1}
 Trạng thái trước {1,3,4,2} trạng thái sau: {1,4,2,3}
Thuật toán
 Tìm chỉ số lớn nhất j mà a jphần tử sẽ bị hoán vị.
1 3 4 2 ( j=2)  j=n-1; while (a[j]>a[j+1]) j--;
 Tìm vị trí đầu tiên k đi ngược từ cuối tập trị với a[k] >
a[j]
1 3 4 2 ( k=3)  k=n; while (a[j]>a[k]) k--;
 Hoán vị a[j] với a[k]
1432
 Lật ngược đoạn aj+1 ... an
1 4 2 3 trạng thái kế tiếp


19


Các hoán vị của X={1,2,3,4}
{1,2,3,4} (đầu)
{1,2,4,3}
{1,3,2,4}
{1,3,4,2}
{1,4,2,3}

{1,4,3,2}
{2,1,3,4}
{2,1,4,3}
{2,3,1,4}
{2,3,4,1}
{2,4,1,3}
{2,4,3,1}

j=1
{3,1,2,4}
{3,4,2,1}
{3,1,4,2}
k=2
{3,2,1,4}
{3,4,2,1}
{3,2,4,1}
{3,4,1,2}
hoán vị
{4,3,2,1}
a[j], a[k]
{3,4,2,1}
{4,1,2,3}
{4,1,2,3}
Đảo mảng
{4,1,3,2}
con từ
{4,2,1,3}
a[j+1] đến
a[n]
{4,2,3,1}

{4,3,1,2}
chỉ số đi từ 1
{4,3,2,1} ( cuối)
20


Viết chương trình hoán vị (1)
void Init (int result[], int k)
{ for (int i=1; i<=k; i++) result[i]=i;
}

int LastConfigure(char result[], int n)
{ for (int i=1; ireturn 0;
return 1;
}
void Output(char result[], int n, int count)
{ printf( ‘’\n Hoan vi thu %d\t’’,count);
for (int i=0; i}

21


Viết chương trình hoán vị (2)
void NextConfigure (int result[],int n)
{ int j=n-1;
// Tìm chỉ số lớn nhất j mà ajwhile(j>0 && result[j] > result[j+1]) j--;
int k=n;

//Tìm vị trí đầu tiên k đi ngược từ cuối tập trị với a[k] > a[j]
while(k>0 && result[j] > result[k]) k--;
// Hoán vị a[j], a[k]
int t= result[j];
result[j]= result[k];
result[k]= t;
//Đảo ngược nhóm trị a[j+1],... a[n]
int left=j+1, right=n;
while (left < right)
{ t = result[left];
result[left]= result[right];
result[right]=t;
left++; right--;
}
}
22


Viết chương trình hoán vị (3)
void Generate(char result[], int n)
{ Init(result, n); //cấu hình ban đầu
int count=1;
Output(result,n,count) // xuat cấu hình đang

int stop = LastConfigure(result,n);
while (!stop)
{
//Sinh cấu hình kế tiếp từ cấu hình đang có
c=NextConfigure(result, n);
count++;

Output(result,n,count); //xuat cấu hình này
stop = LastConfigure(result,n);
}
}

23


Bài tập





Tạo file văn bản hoanvi.out có dạng
Dòng đầu: 1 số nguyên n
Các dòng sau là các hoán vị của tập n phần tử.
Ví dụ:

5
12345
12354
12435
............
24


Thuật toán quay lui
Backtracking


25


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×