MỞ ĐẦU Cụ thể, bài toán có thể được mô tả như sau: Cho một danh sách các mục, mỗi mục có một giá trị (lợi nhuận) và một trọng lượng. Cho trước một giới hạn về trọng lượng mà một cái ba lô (hoặc một không gian) có thể chứa. Mục tiêu là chọn một tập hợp các mục sao cho tổng giá trị là lớn nhất, nhưng tổng trọng lượng không vượt quá giới hạn đã cho. Ví dụ thực tế: Bài toán : Mô tả: Người du lịch muốn chuẩn bị một ba lô để một chuyến du lịch ngắn hạn.
Ba lô của anh ta có giới hạn trọng lượng và anh ta muốn đảm bảo rằng anh ta mang theo những vật dụng quan trọng nhất mà không vượt quá trọng lượng tối đa của ba lô. Dữ liệu vào: 4 Danh sách các mục mà anh ta có thể mang theo (quần áo, máy ảnh, sổ tay, sách, điện thoại, sạc, .) Mỗi mục có một trọng lượng và giá trị tương ứng (có thể là tiện ích hoặc giá trị cá nhân). Dữ liệu ra: Giá trị lớn nhất của balo đó sẽ chứa đựng. Và số lượng những đồ vật mà balo đó.
Mô hình toán học : Ta cần tìm số đồ vật xếp vào balo sao cho tổng giá trị là lớn nhất và và trọng lượng các đồ vật không vượt quá khả năng chịu tải của Balo. Ta có: Capacity là khả năng trọng tải của cái balo. 5 n số đồ vật, và biểu diễn quyết định của bài toánx 1, x 2, …, x n trong đó x i ≥ 0 , i=1 ,n valuei giá trị củavậtthứ ix i weig hti là trọng lượng của vậtthứ ix i Hàm mục tiêu : n ∑ x i .valuei →max i=1 Hàm ràng buộc : { n ∑ x i .weighti ≤ Capacity i=1 xi ≥0 và số nguyên,i=1,…,n CHƯƠNG 2 – CÁC LOẠI BÀI TOÁN TRONG KNAPSACK 2.1 0/1 Knapsack Problem: Trong vấn đề này, mỗi đối tượng có hai lựa chọn: chọn hoặc không chọn. Điều này có nghĩa là bạn không thể chia nhỏ một đối tượng và đặt một phần nó vào túi, mà bạn phải quyết định chọn hoặc không chọn nó nguyên vẹn.
Ví dụ: Nếu bạn có một chiếc ba có khả năng chịu tải 10kg và ba đối tượng với trọng lượng lần lượt là 5kg, 3kg, và 8kg, bạn phải quyết định chọn đối tượng nào và không thể chia nhỏ chúng. - Hạn chế mỗi đồ vật thuộc loại 0 và 1 (không chọn, hoặc chọn) 6 Được phát biểu như sau: n ∑ i=1 x i .valuei →max Sao cho: { n ∑ i=1 x i .weighti ≤Capacity xi=0 hoặc 1 và số nguyên,i=1 ,…,n 2.2 Fractional Knapsack Problem: Trái ngược với 0/1 Knapsack, trong vấn đề này, bạn có thể chia nhỏ đối tượng để đặt một phần của nó vào túi. Điều này tạo ra một mức linh hoạt lớn hơn trong việc chọn lựa, vì bạn có thể chọn một phần của đối tượng để tối ưu hóa giá trị tổng cộng. Ví dụ: Nếu bạn có một túi chịu tải 10kg và một đối tượng có trọng lượng 5kg, bạn có thể đặt nửa đối tượng vào túi để tối ưu hóa giá trị nếu giá trị của đối tượng phụ thuộc vào trọng lượng.
Bài toán: Mỗi đồ vật có thể được chọn một phần của chúng 0 ≤ x i ≤1 Được phát biểu như sau: n ∑ x i .valuei →max i=1 Sao cho: { n ∑ x i .weight i ≤Capacity i=1 0≤ x i ≤ 1 vàsố nguyên,i=1 ,… 7 2.3 Multiple Knapsack Bài toán Multiple Knapsack (MKP) là một phần mở rộng của Bài toán ba lô cổ điển (KP), trong đó có nhiều chiếc ba lô, mỗi chiếc có hạn chế về dung lượng riêng. Trong vấn đề tối ưu hóa này, một tập hợp các vật phẩm cần được phân bổ cho các ba lô khác nhau sao cho tổng giá trị được tối đa hóa trong khi vẫn tôn trọng giới hạn dung lượng riêng của từng ba lô. Mô tả chi tiết như sau: Nhiều Túi: Có nhiều túi, mỗi túi có một giới hạn trọng lượng cụ thể. Nhiều Đối Tượng: Có một danh sách các đối tượng, mỗi đối tượng có trọng lượng và giá trị riêng.
Mục Tiêu: Mục tiêu vẫn là tối ưu hóa tổng giá trị của các đối tượng được đặt vào túi, nhưng với ràng buộc là không vượt quá trọng lượng cho mỗi túi. Thuật toán cho Multiple Knapsack Problem thường kế thừa ý tưởng từ thuật toán cho 0/1 Knapsack, nhưng mở rộng để xử lý nhiều túi. Các phương pháp giải quyết thường sử dụng các kỹ thuật như quy hoạch động hoặc các phương pháp tìm kiếm và tối ưu hóa. Ví dụ, nếu bạn có nhiều túi với khả năng chịu tải là 10kg, 15kg và 20kg, và một danh sách các đối tượng với trọng lượng và giá trị tương ứng, thuật toán sẽ cố gắng phân phối các đối tượng vào các túi để tối ưu hóa tổng giá trị và đồng thời không vượt quá trọng lượng cho mỗi túi.
Bài toán đi tìm lời giải cho n ∑ x ij.value j →max j=1 8 Sao cho { n ∑ x ij.weight ij≤Capacity i ,Vớii ϵ[1 ,m] j=1 x ijϵ {0,1 } ,where j ϵ [ 1,n ],i ϵ[1 ,m ] Chú thích: n là số lượng đồ vật m là số lượng balo value j là giá trị vật phẩm thứ j weight ij là trọng lượng của vật phẩm j trong balo I Capacityi là sức chứa của ba lô i x ij là biến nhị phân cho biết vật thứ j có được chọn để đặt vào balo thứ hay không CHƯƠNG 3 – CÁC PHƯƠNG PHÁP GIẢI BÀI TOÁN KNAPSACK PROBLEM Dữ liệu đầu vào và đầu ra của các thuật toán Input : - Các thuật toán sẽ nhận vào một danh các giá trị của đồ vật (values[]) và danh sách trọng lượng của đồ vật (weights[]) vào cùng một mảng - Nhận vào Trọng tải của balo (Capacity) 9 - Số chỉ mục của 2 mảng weights[], values[] tương ứng với thứ tự đồ vật. Ví dụ: trên hình index 0 tương ứng với vật đầu tiên với: trọng lượng 70 và giá trị 135 Output : - Trả về Kiểu Tuple tự định nghĩa lưu danh sách các đồ vật được chọn hay không(1 – 0) và trả về giá trị tốt nhất Ví dụ : 3.1 Giải quyết bài toán cái túi bằng thuật toán trực tiếp với KapSack 0/1 (Brute-force) 10 Thử tất cả các2n khả năng chọn lựa để tìm ra tập con đối tượng sao cho tổng trọng lượng không vượt quá trọng lượng tối đa cho túi và tổng giá trị là lớn nhất. Phương pháp Brute-Force là một cách tiếp cận đơn giản nhưng không hiệu quả với bài toán Knapsack và Fractional Knapsack do nó thử tất cả các khả năng có thể của việc chọn hoặc không chọn mỗi mục, sau đó kiểm tra xem liệu nó có đáp ứng các ràng buộc hay không. Dưới đây là cách giải bài toán Fractional Knapsack bằng phương pháp Brute-Force: o Tạo tất cả các tổ hợp có thể của việc chọn hoặc không chọn mỗi đối tượng.
Mỗi đối tượng có hai lựa chọn: chọn hoặc không chọn. Do đó, số lượng tổ hợp sẽ là2n , nơi n là số lượng đối tượng. o Kiểm tra từng tổ hợp: Đối với mỗi tổ hợp, tính tổng giá trị và tổng trọng lượng. Kiểm tra xem tổng trọng lượng có vượt quá dung lượng của túi không.
Nếu không, so sánh giá trị với giá trị tối ưu tới thời điểm đó và cập nhật nếu cần. o Trả về giải pháp tối ưu Mặc dù phương pháp Brute-Force có thể đảm bảo tìm ra giải pháp tối ưu, nhưng độ phức tạp thời gian của nó là O( 2n ¿ ,nơi n là số lượng đối tượng. 11 Đối với các bài toán có số lượng đối tượng lớn, phương pháp này trở nên không hiệu quả về mặt thời gian. Ví dụ Bài toán KnapSack 0/1 Problem với giải thuật brute-force: Tổ hợp đồ Tổng trọng lượng (w=10) Tổng giá trị (max) vật Ø 0 $0 {1} 7 $42 {2} 3 $12 {3} 4 $40 {4} 5 $25 {1,2} 7+3=10 42+12 = $54 {1,3} 7+4=11 [11>10] Không khả thi {1,4} 7+5=12 [12>10] Không khả thi {2,3} 3+4=7 12+40=$52 {2,4} 3+5=8 12+25=$37 {3,4} 4+5=9 40+25=$65 12 {1,2,3} 7+3+4=14 [14>10] Không khả thi {1,2,4} 7+3+5=15 [15>10] Không khả thi {1,3,4} 7+4+5=16 [16>10] Không khả thi {2,3,4} 3+4+5=12 [12>10] Không khả thi {1,2,3,4} 7+3+4+5=19 [19>10] Không khả thi Vậy dễ dàng thấy: giá trị lớn balô có thể chứa là $65 với đồ vật 3 và đồ vật 4.
Số tổ hợp của n đồ vật là 2n, độ phức tạp thời gian của nó là O(2n ¿. 4 4 - PersudoCode Thuật toán BruteForce (Trọng số [1 … N], Giá trị [1 … N] Tìm sự kết hợp vật phẩm tốt nhất có thể cho KP • Đầu vào: o Trọng số mảng chứa trọng số của tất cả các mục o Giá trị mảng chứa giá trị của tất cả các mục o Mảng A được khởi tạo bằng 0 được sử dụng để tạo chuỗi bit • Đầu ra trả về mảng với: o 2 phần tử cuối của mảng lần lượt là giá trị tốt nhất và trọng lượng của nó o Các giá trị trước đó là danh sách các đồ vật được chọn 13 - Tiếp theo sử dụng vòng for lồng nhau với vòng for đầu tiên duyệt qua 2n tổ hợp để lọc chọn tổ hợp xét giá trị 14 - Vòng while bên trong sẽ chịu trách nhiệm tạo ra tổ hợp - Vòng for tiếp theo tính toán giá trị của tổ hợp và chọn giá trị tốt nhất - Cuối cùng trả về kết quả 15 Độ phức tạp cho đoạn code: - Time Complexity Analysis [ ] n n 2 1 n 2 ∑ ∑ + ∑ =∑ ¿ ¿ ¿ i=1 j =n k+1 i=1 ¿ ( 2 n ). [1 +…+1 ] ¿ ¿ O ( 2 n∗2n ) ¿ O ( n∗2 ) n - Time Complexity Analysis Thuật toán sử dụng mảng để lưu trữ quyết định tốt nhất, quyết định tạm thời và kết quả. Độ phức tạp không gian của các mảng là O(n), trong đó n là số lượng mục.
Vì độ phức tạp của thuật toán này tăng theo cấp số nhân nên nó chỉ có thể được sử dụng cho các trường hợp nhỏ của Sự cố KnapSack. Mặt khác, nó không đòi hỏi nhiều nỗ lực lập trình để triển khai. Ngoài bộ nhớ được sử dụng để lưu trữ giá trị và trọng lượng của tất cả các mục, thuật toán này yêu cầu mảng hai chiều (A[] và bestChoice[]).2 Giải quyết bài toán cái túi bằng thuật toán tham lam cho bài toán Fractional Knapsack Problem (Greedy) Cách tiếp cận bài toán: 1. Chọn mục có giá trị lớn nhất trong số các mục còn lại; điều này làm tăng giá trị của chiếc ba lô càng nhanh càng tốt.