You are on page 1of 14

1.

Mô tả chi tiết thuật toán;


2. Chỉ rõ phương pháp thiết kế thuật toán trong thuật toán vừa nêu;
3. Xây dựng chương trình bằng ngôn ngữ lập trình C/ C++
4. Thực hiện bài toán với 1 bộ dữ liệu cụ thể bằng thuật toán đã xây dựng
5. Đánh giá thời gian thực hiện của thuật toán
BÀI 1 : Xét bài toán đổi tiền xu cho một số tiền có giá trị bằng n xu ( n nhập từ bàn
phím) sao cho số đồng xu đổi ra là nhỏ nhất. Thiết kế một giải thuật tham lam để đổi
tiền có dùng các đồng xu sau: 5000, 2000, 1000, 500.
1.Mô tả chi tiết thuật toán:
 Đầu tiên, chúng ta sẽ khởi tạo một biến đếm số đồng xu đã đổi ban đầu bằng 0.
 Tiếp theo, chúng ta sẽ lặp lại các bước sau cho đến khi số tiền cần đổi xu về 0:
o Tìm đồng xu lớn nhất mà không vượt quá số tiền cần đổi xu.
o Tăng biến đếm số đồng xu đã đổi lên 1.
o Giảm số tiền cần đổi xu đi giá trị của đồng xu tìm được ở bước trước.
 Kết quả cuối cùng sẽ là số đồng xu đã đổi.

2.Phương pháp thiết kế thuật toán trong thuật toán trên là tham lam (greedy).
Thuật toán luôn chọn đồng xu có mệnh giá lớn nhất mà không vượt quá số tiền
cần đổi xu. Điều này đảm bảo số đồng xu đổi ra là nhỏ nhất.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/ C++ : (trong dev C++)

4.Ví dụ thực hiện bài toán với một bộ dữ liệu cụ thể: giả sử số tiền cần đổi là
7500.
Kết quả sẽ là 3 đồng xu (5000 + 2000 + 500).

5.Đánh giá thời gian thực hiện của thuật toán:

 Thời gian thực hiện của thuật toán này phụ thuộc vào số lượng đồng xu
và giá trị của số tiền cần đổi.
 Trong trường hợp tệ nhất, khi giá trị của số tiền cần đổi lớn và số lượng
đồng xu ít, thuật toán có thể yêu cầu số lần lặp nhiều và thời gian thực
hiện sẽ tăng.
 Tuy nhiên, với số lượng đồng xu và giá trị của số tiền như trong ví dụ
trên, thuật toán chạy rất nhanh và hiệu quả.

Bài 2: Áp dụng giải thuật tham lam để giải bài toán cái túi dạng phân số với các
thông tin về trọn lượng mặt hàng như sau:
Mặt hàng Trọng lượng Giá trị
A 18 25
B 15 24
C 10 25

Giả sử sức chứa về trọng lượng của cái túi là M=20


1.Mô tả chi tiết thuật toán:
Thuật toán giải bài toán cái túi (knapsack problem) dạng phân số theo phương pháp
tham lam có thể được mô tả như sau:

 Bước 1: Tính giá trị trọng lượng cho mỗi mặt hàng bằng cách chia giá trị của
mặt hàng cho trọng lượng của nó.
 Bước 2: Sắp xếp các mặt hàng theo giá trị trọng lượng giảm dần.
 Bước 3: Bắt đầu từ mặt hàng có giá trị trọng lượng cao nhất, đặt mặt hàng vào
túi nếu nó không làm túi quá trọng lượng (M). Cập nhật trọng lượng của túi và
giá trị thu được.
 Bước 4: Lặp lại bước 3 cho đến khi túi đầy hoặc hết mặt hàng.

2.Phương pháp thiết kế thuật toán

Phương pháp tham lam được áp dụng bằng cách luôn chọn mặt hàng có giá trị
trọng lượng lớn nhất trước. Điều này giúp tối ưu hóa giá trị tổng cộng của mặt
hàng đưa vào túi.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/ C++ : (trong dev C++)

4.Trong ví dụ trên, dữ liệu của mặt hàng được đưa vào vector items, và giả sử
túi có trọng lượng tối đa là 20.

5.Đánh giá thời gian thực hiện của thuật toán:

Phương pháp tham lam cho bài toán cái túi dạng phân số có độ phức tạp thời
gian là O(n log n) do bước sắp xếp. Tuy nhiên, đối với số lượng mặt hàng nhỏ,
nó sẽ thực hiện nhanh chóng và hiệu quả.

Bài 3: Cho 9 hoạt động với thời điểm bắt đầu và thời điểm kết thúc của chúng
như sau:

i 1 2 3 4 5 6 7 8 9
Si 1 3 4 2 6 4 10 12 11
Fi 3 4 6 8 10 13 14 15 16
Hãy áp dụng giải thuật tham lam để giải bài toán xếp lịch của các hoạt động
trên
1.Mô tả chi tiết thuật toán:
Bước 1: Sắp xếp các hoạt động theo thời điểm kết thúc tăng dần (Fi).

Bước 2: Chọn hoạt động có thời điểm kết thúc sớm nhất và đưa vào lịch làm
việc.

Bước 3: Loại bỏ những hoạt động mà có thời điểm bắt đầu trước thời điểm kết
thúc của hoạt động đã chọn.

Bước 4: Lặp lại từ bước 2 cho đến khi không còn hoạt động nào.

2.Phương pháp thiết kế thuật toán

Thuật toán sử dụng chiến lược tham lam bằng cách luôn chọn hoạt động có
thời điểm kết thúc sớm nhất có thể để tối ưu hóa số lượng hoạt động được thực
hiện.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/ C++ : (trong dev C++)
4.Thực hiện bài toán với bộ dữ liệu cụ thể:

Trong ví dụ trên, dữ liệu đã được đưa vào mảng activities. Kết quả sẽ là các
hoạt động được chọn và in ra màn hình.
5.Đánh giá thời gian thực hiện của thuật toán :

 Phụ thuộc vào số lượng hoạt động và cách triển khai của ngôn ngữ lập trình.
Tuy nhiên, giải thuật tham lam cho bài toán xếp lịch này có độ phức tạp
thời gian là O(nlogn), trong đó n là số lượng hoạt động. Điều này do cần
thực hiện quá trình sắp xếp các hoạt động theo thời điểm kết thúc trước khi
áp dụng giải thuật tham lam.

Bài 4 : Thiết kế thuật toán tìm dãy con liên tiếp có tổng lớn nhất theo phương pháp
chia để trị

1.Mô tả chi tiết thuật toán:


 Đầu vào: Dãy số nguyên không rỗng A[1..n]
 Đầu ra: Dãy con liên tiếp có tổng lớn nhất
 Bước 1: Chia dãy ban đầu thành hai nửa bằng cách tìm chỉ số giữa m = (l +
r) / 2, với l là chỉ số đầu và r là chỉ số cuối của dãy.
 Bước 2: Đệ quy tìm dãy con liên tiếp có tổng lớn nhất trong dãy con trái và
dãy con phải của dãy ban đầu.
 Bước 3: Tìm dãy con liên tiếp có tổng lớn nhất mà đi qua phần giữa (m) của
dãy ban đầu.
o Tìm dãy con liên tiếp có tổng lớn nhất bắt đầu từ m và đi về phía bên
trái (leftSum).
o Tìm dãy con liên tiếp có tổng lớn nhất bắt đầu từ m+1 và đi về phía
bên phải (rightSum).
o Tổng hợp leftSum, rightSum và A[m] để tìm tổng lớn nhất mà đi qua
phần giữa, gọi là crossSum.
 Bước 4: So sánh tổng lớn nhất trong dãy con trái, dãy con phải và dãy con
đi qua phần giữa, chọn tổng lớn nhất trong số đó làm kết quả.

2.Phương pháp thiết kế thuật toán


 Thuật toán chia để trị chia dãy ban đầu thành các phần nhỏ hơn, giải quyết từng
phần đó, sau đó kết hợp kết quả để có kết quả cuối cùng.

 Trong trường hợp này, dãy ban đầu được chia thành hai phần, và ta tìm dãy con
liên tiếp có tổng lớn nhất trong dãy con trái, dãy con phải và dãy con đi qua
phần giữa. Sau đó, ta so sánh các tổng lớn nhất đó để chọn kết quả cuối cùng.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/ C++ : (trong dev C++)
4. Thực hiện bài toán với bộ dữ liệu cụ thể:

Bộ dữ liệu trong ví dụ trên là mảng arr. Bạn có thể thay đổi giá trị của mảng
này để kiểm tra với các dãy con khác nhau.
5.Đánh giá thời gian thực hiện của thuật toán :

 Thời gian thực hiện của thuật toán chia để trị trong trường hợp này là
O(n log n), với n là kích thước của dãy số ban đầu.
 Việc chia dãy ban đầu thành các phần nhỏ hơn có độ phức tạp O(log n),
và việc tìm tổng lớn nhất trong dãy con đi qua phần giữa mất O(n) thời
gian.
 Tổng cộng, thuật toán có độ phức tạp O(n log n), cho nên đánh giá thời
gian thực hiện là hiệu quả.

Bài 5: Cho số tự nhiên n < 100. Hãy cho biết có bao nhiêu cách phân tích số n thành
tổng của dãy các số nguyên dương (các cách phân tích là hoán vị của nhau chỉ tính là
một cách)
1.Mô tả chi tiết thuật toán:
 Để giải quyết bài toán này, chúng ta có thể sử dụng phương pháp đệ quy và quy
hoạch động.
 Đầu tiên, ta khởi tạo một mảng động dp kích thước (n+1) và ban đầu giá trị tất
cả các phần tử trong mảng đều là 0.
 Gán dp[0] = 1, đại diện cho trường hợp có một cách phân tích số 0 thành tổng
của dãy số nguyên dương.
 Duyệt qua các số nguyên dương từ 1 đến n:
o Với mỗi số i, duyệt qua các số j từ i đến n:
 Tại mỗi bước duyệt, cập nhật giá trị dp[j] bằng tổng của dp[j] và
dp[j-i].
 Sau khi duyệt qua tất cả các số, giá trị dp[n] sẽ chứa số cách phân tích số n
thành tổng của dãy số nguyên dương.

2.Phương pháp thiết kế thuật toán

o Thuật toán được thiết kế theo phương pháp quy hoạch động.
o Sử dụng một mảng động để lưu trữ kết quả phụ thuộc vào kết quả của
các bài toán con nhỏ hơn.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/ C++ : (trong dev C++)
4. Thực hiện bài toán với bộ dữ liệu cụ thể: nhập số nguyên dương vào
lúc chạy

5.Đánh giá thời gian thực hiện của thuật toán :

 Độ phức tạp của thuật toán này là O(n^2), với n là số tự nhiên đầu vào.
 Với giá trị n nhỏ, thuật toán sẽ hoạt động nhanh. Tuy nhiên, với giá trị n
lớn, thuật toán sẽ có độ phức tạp cao và mất thời gian để thực hiện.

Bài 6 : Cần đặt 8 con hậu vào bàn cờ 8x8 sao cho chúng không tấn công nhau, (không
có hai con hậu nào nằm cùng hàng, hoặc cùng cột, hoặc cùng đường chéo).Thiết kế
thuật toán giải bài toán xếp tám hậu theo phương pháp quay lui với các công việc sau:
( Thực hiện từng bước việc đặt 5, 6, 7 con hậu đầu tiên trên bàn cờ 8x8)

1.Mô tả chi tiết thuật toán:


Thuật toán Quay lui để đặt 8 con hậu trên bàn cờ 8x8 sao cho chúng không tấn công
nhau có thể được mô tả như sau:

 Bước 1: Bắt đầu từ hàng đầu tiên (hàng 1).


 Bước 2: Duyệt qua từng ô trên hàng hiện tại.
 Bước 3: Nếu ô hiện tại là một vị trí an toàn để đặt hậu, đặt hậu vào ô đó và
chuyển sang hàng tiếp theo (đệ quy).
 Bước 4: Nếu tất cả các ô trên hàng hiện tại đã được kiểm tra và không có vị trí
an toàn nào, quay lui (trở về trạng thái trước đó) và thử một vị trí khác cho hậu
ở hàng trước đó.
 Bước 5: Lặp lại quá trình trên cho tất cả các hàng và cột.
 Bước 6: Khi đã đặt đủ 8 con hậu, một giải pháp an toàn được tìm thấy.

2.Phương pháp thiết kế thuật toán


Phương pháp Quay lui được sử dụng để thử nghiệm từng lựa chọn và trở về
nếu nó không dẫn đến giải pháp. Ở mỗi bước, thuật toán kiểm tra nếu việc đặt
hậu tại một vị trí cụ thể là an toàn.
3.Xây dựng chương trình bằng ngôn ngữ lập trình C/ C++ : (trong dev C++)
4. Thực hiện bài toán với bộ dữ liệu cụ thể: Chương trình sẽ thử đặt 5 con
hậu đầu tiên trên bàn cờ 8x8.
5.Đánh giá thời gian thực hiện của thuật toán :

Đối với bài toán xếp tám hậu, thuật toán quay lui có độ phức tạp O(8^N), trong
đó N là kích thước bàn cờ (trong trường hợp này là 8). Vì vậy, đối với bài toán
này, thuật toán sẽ có độ phức tạp thời gian tương đối lớn. Tuy nhiên, với kích
thước bàn cờ nhỏ như 8x8, thuật toán vẫn sẽ hoàn thành trong thời gian rất
ngắn và không gây trễ hệ thống.
Bài 7: Cho số tự nhiên n <= 100. Hãy cho biết có bao nhiêu cách phân tích số n thành
tổng của dãy các số nguyên dương, các cách phân tích là hoán vị của nhau chỉ tính là
một cách, với các công việc sau
1.Mô tả chi tiết thuật toán:

 Để giải quyết bài toán này, ta có thể sử dụng phương pháp đệ quy hoặc sử
dụng quy hoạch động.
 Trong phương pháp quy hoạch động, ta sẽ sử dụng một mảng dp[k] để lưu
số cách phân tích số k thành tổng của dãy các số nguyên dương.
 Ban đầu, ta khởi tạo dp[0] = 1 (vì có một cách phân tích số 0 là không chọn
bất kỳ số nào).
 Tiếp theo, ta duyệt qua từng số nguyên dương i từ 1 đến n, và duyệt qua
từng giá trị j trong dãy số từ i đến n.
 Tại mỗi bước lặp, ta cập nhật dp[j] bằng cách cộng thêm dp[j - i] (số cách
phân tích số j - i thành tổng) vào dp[j].
 Cuối cùng, giá trị dp[n] sẽ chứa số cách phân tích số n thành tổng của dãy
các số nguyên dương.
2.Phương pháp thiết kế thuật toán
 Thuật toán sử dụng phương pháp quy hoạch động để tính số cách phân tích
số n thành tổng.
 Sử dụng một mảng dp để lưu số cách phân tích cho các số nhỏ hơn n.
 Duyệt qua từng số nguyên dương và cập nhật giá trị dp tương ứng.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/ C++ : (trong dev C++)
4. Thực hiện bài toán với bộ dữ liệu cụ thể: nhập số nguyên dương vào
lúc chạy

5.Đánh giá thời gian thực hiện của thuật toán :

 Độ phức tạp của thuật toán này là O(n^2), với n là số tự nhiên đầu vào.
 Thuật toán sử dụng hai vòng lặp lồng nhau, mỗi vòng lặp chạy từ 1 đến n, do
đó thời gian thực hiện tăng theo bình phương của n.
 Với n <= 100, thuật toán sẽ hoạt động nhanh và hiệu quả.

Bài 8 : Thiết kế giải thuật tính n! Theo 2 phương pháp: chia để trị và quy hoạch
động.
1.Mô tả chi tiết thuật toán
a) chia để trị
 Nếu n = 0, kết quả là 1.
 Nếu n > 0, kết quả là n nhân với giá trị giai thừa của (n-1).
b) quy hoạch động
 Sử dụng một mảng dp để lưu trữ giá trị giai thừa của các số từ 0 đến n.
 Khởi tạo dp[0] = 1.
 Duyệt từ i = 1 đến n, tính dp[i] bằng cách nhân dp[i-1] với i.
 Kết quả là dp[n].

2.pp thiết kế tt
 Phương pháp chia để trị: Ta chia bài toán thành hai bước nhỏ hơn, tính giai
thừa của (n-1) và nhân với n. Đây là một phương pháp đệ quy.
 Phương pháp quy hoạch động: Ta sử dụng một mảng dp để lưu trữ các giá
trị đã tính toán trước đó và sử dụng chúng để tính giá trị giai thừa của các số
lớn hơn.
3.Trong DEV C++
4.như trên

5.Đánh giá thời gian thực hiện

 Thời gian thực hiện của phương pháp chia để trị là O(n), với n là số
nguyên dương đầu vào.
 Thời gian thực hiện của phương pháp quy hoạch động cũng là O(n), với
n là số nguyên dương đầu vào.
 Cả hai phương pháp đều có độ phứcThời gian thực hiện tương đương
nhau và phụ thuộc vào giá trị của n, vì cả hai phương pháp đều tính toán
lại các giá trị giai thừa trước đó khi cần thiết. Tuy nhiên, phương pháp
quy hoạch động có thể nhanh hơn trong một số trường hợp do không
tính toán lại các giá trị đã tính trước đó.

 Ví dụ, nếu chúng ta muốn tính giai thừa của một số lớn như 1000,
phương pháp chia để trị sẽ thực hiện rất nhiều lần tính toán trùng lặp và
có thể gây hiệu năng kém. Trong khi đó, phương pháp quy hoạch động
chỉ tính toán các giá trị một lần và lưu trữ chúng để sử dụng lại, do đó
thời gian thực hiện sẽ nhanh hơn đáng kể.

Bài 9 : Cho dãy số nguyên A có n phần tử cần được sắp xếp thành dãy số không giảm
theo phương pháp sắp sếp nhanh QuickSort. Hãy thiết kế thuật toán sắp xếp theo
phương pháp chia để trị.
1.Mô tả chi tiết thuật toán chia để trị cho QuickSort:
 Chọn một phần tử chốt (pivot) từ dãy A.
 Chia dãy A thành hai phần: các phần tử nhỏ hơn hoặc bằng pivot và các phần tử
lớn hơn pivot.
 Đệ quy sắp xếp các phần tử nhỏ hơn hoặc bằng pivot và các phần tử lớn hơn
pivot.
 Kết hợp các phần tử đã sắp xếp lại để tạo thành dãy A đã được sắp xếp không
giảm.
2.Phương pháp thiết kế thuật toán:
 Thuật toán chia để trị của QuickSort sử dụng phương pháp chọn pivot để chia
dãy thành các phần tử nhỏ hơn hoặc bằng pivot và các phần tử lớn hơn pivot.
 Sau đó, đệ quy sắp xếp các phần tử nhỏ hơn và các phần tử lớn hơn pivot.
 Cuối cùng, kết hợp các dãy đã sắp xếp lại để tạo thành dãy đã được sắp xếp
không giảm.
3.DEV C++
4.Ví dụ
 Thực hiện bài toán với một bộ dữ liệu cụ thể bằng thuật toán đã xây dựng:
 Sử dụng dãy số {64, 25, 12, 22, 11} để thực hiện thuật toán QuickSort.
 Chọn pivot là 11.

 Chia dãy thành hai phần: {11, 25, 12, Tiếp tục phần 4:

 Chia dãy thành hai phần: {11, 25, 12, 22} và {64}.

 Đệ quy sắp xếp các phần tử nhỏ hơn pivot: {11, 12, 22, 25}.

 Đệ quy sắp xếp các phần tử lớn hơn pivot: {64}.

 Kết hợp các phần tử đã sắp xếp lại để tạo thành dãy đã được sắp xếp không
giảm: {11, 12, 22, 25, 64}.

5. Đánh giá thời gian thực hiện của thuật toán:

Thời gian thực hiện của thuật toán QuickSort phụ thuộc vào bộ dữ liệu và hiệu
suất của việc chọn pivot. Trung bình, QuickSort có độ phức tạp O(n log n)
trong trường hợp trung bình và tốt nhất, và O(n^2) trong trường hợp xấu nhất.
Tuy nhiên, với phương pháp chọn pivot tốt và tối ưu hóa, QuickSort thường có
hiệu suất tốt và được sử dụng rộng rãi trong thực tế.

Bài 10: Cho dãy số nguyên A có n phần tử cần được sắp xếp thành dãy số không giảm
theo phương pháp sắp sếp trộn MergeSort. Hãy thiết kế thuật toán sắp xếp theo
phương pháp chia để trị
1. Mô tả chi tiết thuật toán chia để trị cho MergeSort:
 Chia dãy số A thành hai phần bằng cách chia đều dãy thành hai nửa (trường
hợp dãy có số phần tử lẻ, phần tử ở giữa được chia đều cho hai nửa).
 Đệ quy sắp xếp hai nửa dãy số A.
 Trộn hai dãy đã sắp xếp thành một dãy số đã được sắp xếp không giảm.

2. Phương pháp thiết kế thuật toán:


 Thuật toán chia để trị của MergeSort sử dụng phương pháp chia đều dãy thành
hai nửa.
 Sau đó, đệ quy sắp xếp từng nửa dãy số.
 Cuối cùng, trộn hai dãy số đã sắp xếp thành một dãy số đã được sắp xếp không
giảm.

3. Xây dựng chương trình bằng ngôn ngữ lập trình C/C++:

4.Thực hiện bài toán với bộ dữ liệu cụ thể bằng thuật toán đã xây dựng

5.Đánh giá thời gian thực hiện của thuật toán:


Thời gian thực hiện của thuật toán MergeSort là O(n log n) trong trường hợp trung
bình và trong trường hợp xấu nhất.

Bài 11: Có 1 chiếc túi có thể chứa được một khối lượng w, chúng ta có n loại đồ vật
được đánh số i,…, n. Mỗi đồ vật loại i (i = 1,…, n) có khối lượng ai và có giá trị ci.
Chúng ta muốn sắp xếp các đồ vật vào túi để nhận được túi có giá trị lớn nhất có thể
được. Giả sử mỗi loại đồ vật có đủ nhiều để xếp vào túi. Hãy thiết kế thuật toán giải
bài toán cái túi theo phương pháp tham lam.
1.Mô tả chi tiết thuật toán tham lam cho bài toán cái túi:

 Sắp xếp các đồ vật theo tỷ lệ giá trị trên khối lượng (giá trị trên khối lượng =
giá trị đồ vật / khối lượng đồ vật) giảm dần.
 Bắt đầu từ đồ vật có tỷ lệ giá trị trên khối lượng cao nhất, thêm đồ vật đó vào
túi cho đến khi túi đạt đến khối lượng tối đa w hoặc hết đồ vật.
 Nếu vẫn còn chỗ trống trong túi, chuyển sang đồ vật có tỷ lệ giá trị trên khối
lượng kế tiếp cao nhất và lặp lại quá trình thêm đồ vật vào túi.

2.Phương pháp thiết kế thuật toán:


 Thuật toán tham lam cho bài toán cái túi sắp xếp các đồ vật dựa trên tỷ lệ giá trị
trên khối lượng.
 Sắp xếp các đồ vật theo tỷ lệ giá trị trên khối lượng giảm dần.
 Thêm các đồ vật vào túi theo thứ tự đã sắp xếp cho đến khi túi đạt đến khối
lượng tối đa hoặc hết đồ vật.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/C++:

4.Thực hiện bài toán với bộ dữ liệu cụ thể bằng thuật toán đã xây dựng:
 Giả sử có chiếc túi có khối lượng tối đa W = 50 và có 3 đồ vật với khối lượng
và giá trị tương ứng như sau:
 Đồ vật 1: khối lượng 10, giá trị 60
 Đồ vật 2: khối lượng 20, giThực hiện chương trình trên

5.Đánh giá thời gian thực hiện của thuật toán:


Độ phức tạp thời gian của thuật toán tham lam cho bài toán cái túi là O(n log
n), trong đó n là số lượng đồ vật. Việc sắp xếp các đồ vật theo tỷ lệ giá trị trên
khối lượng yêu cầu O(n log n) và việc thêm đồ vật vào túi có độ phức tạp O(n).
Vì vậy, tổng thời gian thực hiện của thuật toán là O(n log n), trong đó n là số
lượng đồ vật.

Bài 12 : Có 1 chiếc túi có thể chứa được một khối lượng w, chúng ta có n loại
đồ vật được đánh số i,…, n. Mỗi đồ vật loại i (i = 1,…, n) có khối lượng ai và
có giá trị ci. Chúng ta muốn sắp xếp các đồ vật vào túi để nhận được túi có giá
trị lớn nhất có thể được. Hãy thiết kế thuật toán giải bài toán cái túi theo
phương pháp quy hoạch động.

1.Mô tả chi tiết thuật toán quy hoạch động cho bài toán cái túi:

 Sử dụng một bảng hai chiều dp có kích thước (n+1) x (w+1), trong đó n là số
lượng đồ vật và w là khối lượng tối đa của túi.
 Khởi tạo giá trị ban đầu của bảng dp là 0.
 Duyệt qua từng đồ vật và khối lượng từ 1 đến w:
 Nếu khối lượng đồ vật i nhỏ hơn hoặc bằng khối lượng hiện tại, thực
hiện công thức quy hoạch động để cập nhật giá trị tối đa của túi: dp[i][j]
= max(dp[i-1][j], dp[i-1][j-ai] + ci), trong đó dp[i-1][j] là giá trị tối đa
của túi khi không chứa đồ vật i và dp[i-1][j-ai] + ci là giá trị tối đa của
túi khi chứa đồ vật i.
 Nếu khối lượng đồ vật i lớn hơn khối lượng hiện tại, giá trị tối đa của túi
không thay đổi: dp[i][j] = dp[i-1][j].
 Giá trị tối đa của túi nằm ở vị trí dp[n][w].

2.Phương pháp thiết kế thuật toán:

 Sử dụng phương pháp quy hoạch động để giải quyết bài toán cái túi.
 Xây dựng bảng dp để lưu trữ giá trị tối đa của túi khi xét các đồ vật và khối
lượng khác nhau.
 Sử dụng công thức quy hoạch động để cập nhật giá trị tối đa của túi tại mỗi
bước duyệt.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/C++

4.Thực hiện bài toán với bộ dữ liệu cụ thể bằng thuật toán đã xây dựng:

 Trong chương trình trên, đã được xây dựng một bộ dữ liệu mẫu với 3 đồ vật có
khối lượng và giá trị tương ứng.
 Bộ dữ liệu mẫu có khối lượng tối đa của túi là 50.
 Kết quả sẽ hiển thị giá trị lớn nhất của túi sau khi sắp xếp các đồ vật vào túi.
5.Đánh giá thời gian thực hiện của thuật toán:
 Thời gian thực hiện của thuật toán sẽ phụ thuộc vào số lượng đồ vật (n) và khối
lượng tối đa của túi (w).
 Với bài toán này, thuật toán quy hoạch động có độ phức tạp O(nw), trong đó n
là số lượng đồ vật và w là khối lượng tối đa của túi.
 Thời gian thực hiện của thuật toán có thể tăng theo cấp số nhân khi n và w tăng
lên, do đó cần đảm bảo rằng dữ liệu đầu vào không quá lớn để thuật toán chạy
trong thời gian hợp lý.

Bài 13: Cho một dãy số nguyên dương (a0 ,a1 ,…,an-1 ) và một số nguyên
dương M. Ta cần tìm các dãy con của dãy sao cho tổng của các phần tử trong
dãy con đó bằng M. Chẳng hạn, với dãy số (7,1,4,3,5,6) và M=11, thì các dãy
con cần tìm là (7,1,3), (7,4), (1,4,6) và (5,6). Thiết kế TT giải bài toán bằng
phương pháp quay lui

1.Mô tả chi tiết thuật toán quay lui cho bài toán tìm các dãy con có tổng bằng M:
 Sử dụng phương pháp quay lui để liệt kê tất cả các dãy con có tổng bằng M.
 Duyệt qua từng phần tử trong dãy số và xây dựng các dãy con bằng cách chọn
hoặc không chọn phần tử hiện tại.
 Nếu tổng của các phần tử đã chọn bằng M, thì đó là một dãy con thỏa mãn yêu
cầu và được lưu trữ.
 Tiếp tục quay lui để thử tất cả các trường hợp có thể bằng cách chọn hoặc
không chọn các phần tử tiếp theo.
 Khi đã duyệt hết tất cả các phần tử, thuật toán dừng lại.

2.Phương pháp thiết kế thuật toán:

 Sử dụng phương pháp quay lui để liệt kê tất cả các dãy con có tổng bằng M.
 Dùng một mảng visited để đánh dấu các phần tử đã được chọn trong quá trình
quay lui.
 Duyệt qua từng phần tử trong dãy số và thử chọn và không chọn phần tử hiện
tại.
 Nếu tổng các phần tử đã chọn bằng M, lưu trữ dãy con và tiếp tục quay lui.
 Sau mỗi bước quay lui, ta phải bỏ phần tử đã chọn trước đó để thử các trường
hợp khác.

3.Xây dựng chương trình bằng ngôn ngữ lập trình C/C++:
4.

5.Đánh giá thời gian thực hiện của thuật toán:

 Độ phức tạp thời gian của thuật toán quay lui trong trường hợp tồi nhất là
O(2^n), với n là số phần tử trong dãy số.
 Trong trường hợp này, chương trình sẽ liệt kê tất cả các dãy con có tổng bằng
M, vì vậy thời gian thực hiện sẽ phụ thuộc vào số lượng dãy con thỏa mãn yêu
cầu.
 Điều này có thể tăng đáng kể khi số lượng dãy con tăng lên, đặc biệt là khi tổng
M lớn và các phần tử trong dãy số gần nhau, gần M.
 Do đó, thời gian thực hiện của thuật toán có thể khá lớn trong một số trường
hợp, và cần được cân nhắc khi áp dụng cho dữ liệu lớn.

Bài 14: Cho 1 bàn cờ nxn, có n 2 . Một quân mã được di chuyển tuân theo luật chơi
cờ vua được đặt trên bàn cờ tại ô đầu tiên có tọa độ x0, y0. Cần tìm 1 lộ trình gồm n2
– 1 bước sao cho nó phủ toàn bộ bàn cờ (mỗi ô được đi qua đúng 1 lần). Thiết kế TT
giải bài toán bằng phương pháp quay lui

1.Mô tả chi tiết thuật toán:

 Đầu tiên, khởi tạo bàn cờ là một ma trận kích thước nxn, ban đầu tất cả các ô
đều được đánh dấu là chưa được đi qua.
 Bắt đầu từ ô có tọa độ (x0, y0), đặt quân mã vào ô này và đánh dấu là đã đi
qua.
 Tiến hành di chuyển quân mã qua các ô còn lại trên bàn cờ bằng cách sử dụng
phương pháp quay lui.
 Đối với mỗi bước di chuyển, kiểm tra xem quân mã có thể di chuyển tới các ô
chưa đi qua và nằm trong giới hạn của bàn cờ hay không.
 Nếu quân mã có thể di chuyển tới một ô hợp lệ, đặt quân mã vào ô đó, đánh
dấu là đã đi qua và tiến hành đệ quy để tìm bước di chuyển tiếp theo.
 Nếu không tồn tại bước di chuyển tiếp theo hợp lệ, quay lui về bước trước đó
và thử các bước di chuyển khác.
 Quá trình quay lui diễn ra cho đến khi tìm được lộ trình hoặc không còn bước
di chuyển hợp lệ nào.
2.Phương pháp thiết kế thuật toán:

 Sử dụng phương pháp quay lui để thử tất cả các khả năng di chuyển của quân
mã trên bàn cờ.
 Sử dụng đệ quy để thực hiện quay lui và tìm kiếm lộ trình.
 Sử dụng một mảng 2 chiều để lưu trạng thái của bàn cờ và đánh dấu các ô đã đi
qua.

3.Chương trình C++:

4.

5.Đánh giá thời gian thực hiện của thuật toán:

 Thời gian thực hiện của thuật toán sẽ phụ thuộc vào kích thước bàn cờ và vị trí
ban đầu của quân mã.
 Trong trường hợp xấu nhất, thuật toán có thể phải thử tất cả các khả năng di
chuyển của quân mã, tức là O(8^n^2), với n là kích thước bàn cờ.
 Tuy nhiên, trong nhiều trường hợp, thuật toán sẽ tìm được lời giải sớm hơn và
dừng lại.
 Đánh giá thời gian cụ thể yêu cầu thực hiện trên một bộ dữ liệu cụ thể và môi
trường cụ thể.

You might also like