Tải bản đầy đủ (.docx) (12 trang)

Four Algorithm: Next Generation, Recursion, Backtracking, Branchand Bounch

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 (325.21 KB, 12 trang )

BÁO CÁO VỀ 4 THUẬT TỐN
1.Mơ hình thuật tốn sinh (Next Generation Algorithm)

1.1. Thuật toán tổng quát
begin

Bước1 (Khởi tạo):
<Thiết lập cấu hình đầu tiên>;

Bước 2 (Bước lặp):
while (<Lặp khi cấu hình chưa phải cuối cùng>) do
<Đưa ra cấu hình hiện tại>;
<Sinh ra cấu hình kế tiếp>;
endwhile;

End.
1.2. Ứng dụng với bài tập trên code.ptit
1.2.1. XÂU AB CÓ ĐỘ DÀI N

1.2.1.1. Lý do tiếp cận
- Bài toán yêu cầu in ra các xâu AB có độ dài n, tương tự như in ra các

xâu nhị phân
 Ứng dụng trực tiếp thuật toán sinh kế tiếp (sinh nhị phân).
1.2.1.2. Source code

1. #include<bits/stdc++.h>
2. using namespace std;
3. #define MAX 100

4. vector<int> arr(MAX);



5. int n;

6. bool check = true;

7.

8. void first() {

9. for(int i = 1; i <= n; i++ )

10. arr[i] = 0;

11. }

12.

13. void output() {

14. for(int i = 1; i <= n; i++)

15. cout << (char) (arr[i] + 'A');

16. cout << ' ';

17. }

18.

19. void next() {


20. int i = n;

21. while(i > 0 && arr[i]) {

22. arr[i] = 0;

23. i--;

24. }

25. if(i > 0)

26. arr[i] = 1;

27. else check = false;

28. }

29.

30. int main() {

31. int t;

32. cin >> t;

33. while(t--) {

34. cin >> n;


35. first();

36. while(check) {

37. output();

38. next();

39. }

40. check = true;

41. cout << endl;

42. }

43. return 0;

44. }

1.2.2. TỔNG DÃY CON = K

1.2.2.1. Lý do tiếp cận

- Bài toán yêu cầu in ra tất cả các tập con của dãy gồm n phần tử sao

cho tổng các phần tử trong dãy con bằng k. Vì vậy ta cần phải duyệt

qua tất cả các tập con của dãy và kiểm tra xem tổng các phần tử có


bằng k hay khơng. Nếu có thì in ra dãy con đó. Sau cùng ta sẽ in ra số

dãy con hợp lệ.

 Sử dụng thuật tốn sinh tổ hợp để tìm ra các dãy con và kiểm tra xem

tổng của chúng có bằng k hay khơng.

1.2.2.2. Source code

1. #include<bits/stdc++.h>

2. #define MAX 1000

3. int arr[MAX], tmp[MAX], n, k, dem = 0, sum = 0;

4. bool check = true;

5. using namespace std;

6.

7. void first() {

8. for(int i = 0; i < n; i++) {

9. cin >> arr[i];

10. tmp[i] = 0;


11. }

12. }

13.

14. void next() {

15. int i = n - 1;

16. while( i >= 0 && tmp[i] == 1) {

17. tmp[i] = 0;

18. i--;

19. }

20. if(i < 0)

21. check = false;// stop

22. else

23. tmp[i] = 1;

24. }

25.


26. void output() {

27. for(int i = 0; i < n; i++)

28. if(tmp[i] == 1)

29. sum += arr[i];

30. if(sum == k) {

31. for(int i = 0; i < n; i++) {

32. if(tmp[i] == 1)

33. cout << arr[i] << " ";

34. }

35. cout << endl;

36. ++dem;

37. }

38. }

39.

40. int main() {


41. cin >> n >> k;

42. first();

43. while(check) {

44. next();

45. sum = 0;

46. output();

47. }

48. cout << dem << endl;

49. }
2.Mơ hình thuật tốn đệ quy (Recursion Algorithm)

2.1. Thuật toán tổng quát

void Recursion(Test(i)) {

If(<điều kiện dừng>) {

<Giải Test(i) với điều kiện dừng>;

}


Else {

<Giải Test(i + 1) giống như Test(i): Recursion(Test(i+1)) >;

}

}

2.2. Ứng dụng với bài tập trên code.ptit
2.2.1. LIỆT KÊ TỔ HỢP

2.2.1.1. Lý do tiếp cận
Bài toán yêu cầu in ra tổ hợp, ta duyệt từ đầu cho đến cuối mảng, ở

đây có thể dùng đệ quy như sau:

- Trong hàm generate() của đoạn mã, đệ quy được sử dụng để tạo ra tất cả các tổ
hợp chập K của tập các phần tử khác nhau trong mảng A[].

- Bước đệ quy bắt đầu với điều kiện dừng. Nếu K bằng 0, tức là đã thêm đủ số
lượng phần tử cần thiết vào tổ hợp (B), thì hàm sẽ in tổ hợp hiện tại ra màn hình
và kết thúc

- Nếu index đã duyệt qua hết tất cả các phần tử trong mảng A, hàm cũng sẽ kết
thúc.

- Nếu K không bằng 0 và index chưa duyệt hết mảng, hàm sẽ tiếp tục gọi đệ quy:
o Đầu tiên, hàm sẽ chọn phần tử tại vị trí index trong A và thêm vào tổ hợp B.
o Sau đó, hàm gọi đệ quy bằng cách giảm giá trị K đi 1 để tìm các phần tử
còn lại.

o Sau khi đệ quy hoàn tất, hàm sẽ bỏ phần tử cuối cùng ra khỏi
currentCombination để chuẩn bị cho việc chọn phần tử tiếp theo.

2.2.1.2. Source code

1. #include<bits/stdc++.h>

2. using namespace std;

3.

4. void generate(const vector<int>& A, vector<int>& B, int index, int k) {

5. if (k == 0) {

6. for (int num : B)

7. cout << num << " ";

8. cout << endl;

9. return;

10. }

11. if (index == A.size())

12. return;

13. while (index < A.size() - 1 && A[index] == A[index + 1])


14. index++;

15. B.push_back(A[index]);

16. generate(A, B, index + 1, k - 1);

17. B.pop_back();

18. generate(A, B, index + 1, k);

19. }

20.

21. int main() {

22. int n, k;

23. cin >> n >> k;

24. vector<int> A(n);

25. for (int i = 0; i < n; i++)

26. cin >> A[i];

27. sort(A.begin(), A.end());

28. vector<int> B;


29. generate(A, B, 0, k);

30. return 0;

31. }

2.2.2. ĐẶT TÊN - 2

2.2.2.1. Lý do tiếp cận
- Có thể coi bài tốn là tìm tổ hợp k phần tử của n phần tử cho trước

2.2.2.2. Source code

1. #include <bits/stdc++.h>

2. using namespace std;

3.

4. void generatename(string& name, vector<char>& chucai, int k, int tmp) {

5. if(k == 0) {

6. cout << name << endl;

7. return;

8. }


9. else {

10. for(int i = tmp; i < chucai.size(); i++) {

11. name.push_back(chucai[i]);

12. generatename(name, chucai, k - 1, i + 1);

13. name.pop_back();

14. }

15. }

16. }

17.

18. int main() {

19. int t;

20. cin >> t;

21. while(t--) {

22. int n, k;

23. cin >> n >> k;


24. vector<char> chucai(n);

25. for(int i = 0; i < n; i++)

26. chucai[i] = 'A' + i;

27. string name = "";

28. generatename(name, chucai, k, 0);

29. }

30. }

3.Mô hình thuật tốn quay lui (Backtracking Algorithm)

3.1. Thuật toán tổng quát
void Backtracking(int i) {

for(int j = <Khả năng 1>; j <= n; j++) {
if(<Khả năng j đúng>) {
X[i] = <Khả năng j>;
if(i == n) result();
else Backtracking(i + 1);
}

}
}

3.2. Ứng dụng với bài tập trên code.ptit


3.2.1. XÂU NHỊ PHÂN CÓ K BIT 1

3.2.1.1. Lý do tiếp cận
- Bài toán yêu cầu in ra tất cả các dãy nhị phân độ dài n có k bit 1.

- Giải thích đệ quy: hàm quay lui sẽ sinh từng bit nhị phân thứ tự từ 1

cho đến n

- Điều kiện dừng: khi đã duyệt đến cuối mảng

3.2.1.2. Source code

1. #include<bits/stdc++.h>

2. #define MAX 100

3. using namespace std;

4.

5. int n, k, arr[MAX] = {}, dem = 0;

6.

7. void output() {

8. for (int i = 1; i <= n; ++i) cout << arr[i];


9. cout << endl;

10. }

11.

12. void generate(int tmp) {

13. for (int i = 0; i <= 1; ++i) {

14. arr[tmp] = i;

15. if(tmp == n) {

16. int dem = 0;

17. for (int i = 1; i <= n; ++i)

18. dem += arr[i];

19. if(dem == k)

20. output();

21. }

22. else generate(tmp + 1);

23. }


24. }

25.

26. int main() {

27. int t;

28. cin >> t;

29. while(t--) {

30. cin >> n >> k;

31. generate(1);

32. }

33. return 0;

34. }

3.2.2. HAHAHA

3.2.2.1. Lý do tiếp cận
- Khả năng
3.2.2.2. Source code

3.2.2.3. Lý do tiếp cận


3.2.2.4. Source code

1. #include<bits/stdc++.h>

2. using namespace std;

3. int n;

4. vector<char> vc;

5. char a[2] = {'A', 'H'};

6.

7. void output(){

8. for(int i = 1; i <= n; ++i) cout << vc[i];
== 1)
9. cout << endl;

10. }

11.

12. void generate(int i) {

13. for(int j = 0; j < 2; ++j) {

14. if(vc[i - 1] == 'H' and j


15. continue;

16. vc[i] = a[j];

17. if(i == n - 1)

18. output();

19. else

20. generate(i + 1);

21. }

22. }

23.

24. int main() {

25. int t = 1;

26. cin >> t;

27. while(t--) {

28. cin >> n;

29. if(n == 2) {


30. cout << "HA" << endl;

31. continue;

32. }

33. vc.resize(n + 1);

34. vc[1] = 'H';

35. vc[n] = 'A';

36. generate(2);

37. }

38. return 0;

39. }

4.Thuật toán nhánh cận (Branch-and Bounch Algorithm)

4.1. Thuật toán tổng quát
void Brand-andBound (k) {

for( <a(k) thuộc A(k)>) {
if(<chấp thuật a(k)>) {
x(k) = a(k);
if(k == n)
<Cập nhật max (hoặc min)>;

Else if( g(a(1), a(2), ..., a(k)) <= f*)
Brand-andBound (k + 1);
}

}
}

4.2. Ứng dụng với bài tập trên code.ptit
4.2.1. Bài 1
4.2.1.1. Lý do tiếp cận
4.2.1.2. Source code
4.2.2. Bài 2
4.2.2.1. Lý do tiếp cận
4.2.2.2. Source code


×