pháp sinh và ứng dụng trong bài toán liệt kê Nhóm 2 1.Nguyễn Thị Duyên 2.Lê Huy Dưỡng 3.Nguyễn Hữu Sáng 4.Đỗ Ngọc Hậu 5.Nguyễn Duy Quân Phương pháp sinh • Phương pháp sinh là phương pháp mà từ một cấu hình tổ hợp nào đó thỏa mãn yêu cầu của bài toán liệt kê, ta có thể suy ra được cấu hình tổ hợp tiếp theo của bài toán. Phương pháp sinh • Điều kiện để bài toán liệt kê có thể được giải bằng phương pháp sinh: 1. Tập hợp các cấu hình tổ hợp thỏa mãn bài toán phải có 1 thứ tự nào đó. Với thứ tự đó ta có thể xác định được cấu hình tổ hợp đầu tiên và cuối cùng trong thứ tự. 2. Ta phải xây dựng được thuật toán “sinh kế tiếp” để suy ra cấu hình tiếp theo (trong thứ tự nêu trên) sau 1 cấu hình tổ hợp bất kì nào (không phải cuối cùng). Phương pháp sinh • Mô tả thuật toán: 1. Khởi tạo cấu hình ban đầu (trong thứ tự). Nếu muốn liệt kê hết các cấu hình thì cấu hình khởi tạo chính là cấu hình đầu tiên trong thứ tự ta đã xác định được. 2. Tạo 1 vòng lặp, thực hiện hàm “sinh kế tiếp” từ cấu hình khởi tạo, điều kiện dừng là khi cấu hình “sinh” được là cấu hình cuối cùng mà ta đã xác định được ban đầu. Áp dụng vào bài toán Liệt kê tất cả những dãy nhị phân độ dài n • Nhận xét: Bài toán này hoàn toàn thỏa mãn 2 điều kiện để có thể áp dụng phương pháp sinh. • Giả sử các cấu hình có dạng b1 b2 b3…bi…bn – Với bi nhận một trong 2 giá trị 0 và 1. • Điều kiện 1: – Mỗi cấu hình này là biểu diễn nhị phân của 1 số nguyên f(x). Khi đó thứ tự của các cấu hình có thể xem như thứ tự của các số nguyên tương ứng. Ta có cấu hình a < c khi f(a) < f(c). – Với thứ tự trên ta hoàn toàn xác định được cấu hình đầu tiên của dãy nhị phân độ dài n là (000…0)n phần tử và cầu hình cuối cùng là (111…1)n phần tử Áp dụng vào bài toán Liệt kê tất cả những dãy nhị phân độ dài n • Điều kiện 2: – Ta có thể xây dựng được thuật toán suy ra cấu hình kế tiếp 1 cấu hình đã biết trong thứ tự trên bằng cách đơn giản là cộng 1 vào số nhị phân tương ứng với cấu hình đã biết. Ví dụ: (011) + 1 = (100) – Ta có thể cụ thể hóa thuật toán này như sau: • Cho i chạy giảm dần từ n (i = n, n-1, …). Nếu bi = 1 thì gán bi = 0 và tiếp tục.Nếu bi = 0 thì gán bi = 1 và dừng lại. Lúc này ta được 1 cấu hình mới kế tiếp cấu hình lúc đầu. Cài đặt chương trình dùng ngôn ngữ C++ • #include<iostream.h> • #include<conio.h> //Hàm sinh cấu hình kế tiếp từ 1 cấu hình đã biết trong dãy thứ tự • int NextBitString(int a[], int i) • { • while(a[i]==1) • { • if(i==0) return 1; • a[i] = 0; • i--; • } • a[i] = 1; • return 0; • } //Hàm in ra 1 cấu hình • void print(int a[], int n) • { • for(int i = 0; i < n; i++) • cout<<a[i]<<" "; • cout<<endl; • } Cài đặt chương trình dùng ngôn ngữ • void main() C++ • { • int i, *a, c = 0; • cout<<"Nhap vao so phan tu cua day nhi phan: "; • cin>>i; • //Cấp bộ nhớ cho mảng a • a = new int[i]; • //Khởi tạo giá trị cho mảng a ( khởi tạo cấu hình tổ hợp đầu tiên (000…0) ) • for(int j = 0; j<i; j++) • a[j] = 0; • cout<<endl<<"Cac cau hinh to hop cua day so nhi phan do dai "<<i<<" :"<<endl<<endl; • do • { print(a, i); c++;} • while(NextBitString(a, i-1)==0); • cout<<endl<<c<<" cau hinh da duoc liet ke!!!"; • delete a; • getch(); • }