Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 11

Chương II: Kỹ thuật đệ quy...

1. Thuật toán đệ quy


2. Đánh giá độ phức tạp của các thuật toán
đệ quy
3. Một số bài toán sử dụng thuật toán quay
lui
2. Đánh giá độ phức tạp của các
thuật toán đệ quy
 Xây dựng công thức truy hồi theo g(n).
 Giải công thức truy hồi để xác định g(n).
Ví dụ: float Power(float a, int n)
{ if (n==0) return 1;
else return a* Power(a,n-1);
}
Suy ra: g(0)=1 và g(n)=g(n-1)+1
 g(n) = n+1  T(n) = O(n+1) = O(n)
3. Một số bài toán sử dụng thuật
toán quay lui
Có dạng:
Hãy xác định các bộ gồm n thành phần:
(x1, x2, ..., xn) thoả mãn điều kiện B nào đó.
Với xi được chọn từ tập Si cho trước gồm ni
phần tử (i=1..n).

Ví dụ: Xác định tất cả các bộ gồm n thành


phần (x[1], x[2], ..., x[n]), trong đó: x[i] là các
số nguyên nhận giá trị từ 1 đến m (i=1..n).
Một phương pháp giải quyết
Khi cần xác định xi, ta giả sử đã xác định được i-1 thành
phần: x1, x2,..., xi-1. Để xác định thành phần xi, ta duyệt tất
cả các khả năng có thể có của nó.
Với mỗi khả năng j ta luôn kiểm tra xem j có được chấp
nhận không?
 Nếu chấp nhận j, thì xác định x i theo khả năng j.
Tiếp đến kiểm tra, nếu i < n thì ta tiến hành xác định x i+1,
ngược lại (i=n) thì ta được một lời giải.
Rồi kiểm tra khả năng j tiếp theo của xi.
 Nếu tất cả các khả năng của j không có khả năng nào
được chấp nhận thì quay lại bước trước để xác định lại
xi-1. (Cơ chế đệ quy giúp có thể thực hiện được điều này)
Minh hoạ
void Try(int i) //Thử xem xi sẽ nhận giá trị nào
{
for <mỗi khả năng j của xi>
{ if (<chấp nhận j>)
{ xi = j;
if (i==n) <Ghi nhận một lời giải>;
else Try (i+1);
}
}
}
main() //Nội dung chương trình chính
{ <Khai báo và khởi tạo các biến của chương trình>;
Try(1);
}
Ví dụ: Liệt kê các số nhị phân gồm
n chữ số
void Try(int i)
{ int j;
for (j=0; j<=1; j++)
{ x[i]=j;
if (i==n) print(x);
else Try(i+1);
}
}
Trong đó:
1. Chương trình chính:
main()
{ int x[10];
int n;
cin>>n;
Try(1);
}
2. void print(int x[])
{ int k;
for (k=1; k<=n; k++)
cout<<x[k];
cout<<endl;
}
Ví dụ: Liệt kê các hoán vị của n
void Try(int i)
{ int j;
for (j=1; j<=n; j++)
{
if (b[j]==1)
{ x[i]=j;
b[j]=0;
if (i==n) print(x);
else Try(i+1);
b[j]=1;
}
}
}
Trong đó:
main() //Chương trình chính
{ int x[10];
int b[10];
int n, i;
cin>>n;
for (i=1; i<=n; i++)
b[i]=1;
Try(1);
}
Ví dụ: Liệt kê các tổ hợp chập k
của n phần tử (1..n)
void Try(int i)
{ int j;
for (j=1; j<=n; j++)
{ if ((b[j]==1) && (j>x[i-1]))
{ x[i]=j;
b[j]=0;
if (i==k) print(x);
else Try(i+1);
b[j]=1;
}
}
}
Chương trình chính:
main()
{ int x[10];
int b[10];
int n, k, i;
cin>>n; cin>>k;
x[0]=0;
for (i=1; i<=n; i++) b[i]=1;
Try(1);
}

You might also like