Biến thể của vấn đề ba lô


11

Làm thế nào bạn sẽ tiếp cận vấn đề ba lô trong một tình huống lập trình động nếu bây giờ bạn phải giới hạn số lượng vật phẩm trong ba lô bằng một hằng số ? Đây là cùng một vấn đề (trọng lượng tối đa của , mỗi mục có một giá trị và trọng lượng ) nhưng bạn chỉ có thể thêm item (s) vào ba lô và rõ ràng là cần phải tối ưu hóa giá trị của ba lô.W v w ppWvwp

Chúng ta có cần một chiều thứ 3 hay chúng ta có thể tìm thấy một cách tiếp cận khác mà không có nó. Tôi đã cố gắng chỉ đơn giản là thêm số lượng vật phẩm trong chiếc ba lô trong ô và lấy giá trị tối đa ở cuối cùng với số lượng vật phẩm <= nhưng nó không phải là giải pháp TỐT NHẤT.p


Đây là một bài tập về nhà tốt đẹp. Bạn đã thử những gì? Bạn có thoải mái khi làm chương trình năng động? (Nếu không, có thể thử một số bài tập để thực hành với nó.) Bạn đã nghiên cứu thuật toán lập trình động tiêu chuẩn cho bài toán về chiếc ba lô chưa? Hãy tìm một cách để sửa đổi cách tiếp cận tiêu chuẩn đó. Nhiệm vụ chính của bạn là thiết kế tập hợp các bài toán con nên là gì. Trong cách tiếp cận tiêu chuẩn, một bài toán con được đặc trưng bởi một tham số (giới hạn về trọng lượng của các mục). Bạn có thể cân nhắc sử dụng hai tham số (vì vậy một tập hợp các bài toán con lớn hơn). Hãy thử các khả năng khác nhau - bạn nhận được gì?
DW

Câu trả lời:


9

Câu hỏi rất hay!

Bạn đúng hai lần:

  1. Tuyên truyền số lượng vật phẩm trong ba lô không dẫn đến giải pháp tối ưu.
  2. Một giải pháp bao gồm thêm một chiều thứ ba. Điều này khá đơn giản nhưng cần phải tính đến một số sự thật khi làm như vậy. Lưu ý tuy nhiên đó không phải là sự thay thế duy nhất

Sau đây, tôi giả sử rằng bạn đã quen thuộc với giải pháp dựa trên lập trình động. Cụ thể, tôi sẽ không thảo luận về cách di chuyển ngược bảng để xác định giải pháp .

Trước tiên chúng ta hãy tập trung vào trường hợp điển hình: số lượng vật phẩm không bị hạn chế . Trong trường hợp này, bạn chỉ cần xây dựng một bảng trong đó T i , j chứa giá trị tối ưu khi công suất tổng thể của chiếc ba lô bằng i và chỉ các mục j đầu tiên được xem xét. Từ đây:TTi,jij

Ti,j=max{Ti,j1,Tiwj,j1+vj}

trong đó và ứng với trọng lượng và giá trị của mục thứ . Nếu là công suất tổng thể của chiếc ba lô của bạn và có tổng số mặt hàng thì giải pháp tối ưu được đưa ra bởi . Thuật toán này được biết là chạy trong thời gian giả đa thức và một trong những nét đẹp của nó là nó chỉ xem xét những kết hợp phù hợp với công suất tối đa.v j j C N T C , NwjvjjCNTC,N

Tuy nhiên, điều này là không đủ khi thêm ràng buộc của bạn: số lượng mục tối đa . Lý do là công thức lặp lại trước đó không tính đến các kết hợp khác nhau của các mục:p

  1. Đầu tiên, nếu thì sao cho những -thứ mục được thêm vào ba lô mặc dù số lượng tối đa các mặt hàng xem xét, --- để bạn có thể vi phạm hạn chế của bạn. Chà, bạn có thể bị cám dỗ ở đây để áp dụng công thức trước đó theo dõi số lượng vật phẩm được chèn ở mỗi bước và không thêm các vật phẩm khác nếu số lượng vật phẩm hiện tại trong ba lô vượt quá nhưng,Ti,j1<(Tiwj,j1+vj)Ti,j=(Tiwj,j1+vj)jpp
  2. Thứ hai, nếu thì để mục này không được thêm nhưng đó có thể là một sai lầm lớn trong trường hợp giải pháp tối ưu đã bao gồm số lượng vật phẩm tối đa để chèn vào ba lô. Lý do là chúng tôi không so sánh đúng: một mặt, để bảo tồn giải pháp tối ưu bao gồm các mục được chọn trong số các mục trước ; mặt khác, để chèn mục thứ và, ngoài ra, hãy xem xét tập hợp con tốt nhất với các mục trong số các mục trước .Ti,j1>(Tiwj,j1+vj)Ti,j=Ti,j1Ti,j1p(j1)j(p1)(j1)

Vì vậy, một giải pháp đầu tiên bao gồm thêm một chiều thứ ba. Đối với trường hợp của bạn, hãy để là giải pháp tối ưu khi công suất của ba lô là , chỉ các mục đầu tiên được xem xét và không được phép đặt nhiều hơn mục trong ba lô. Hiện nay,Ti,j,kijk

  • Nếu bạn đang tính toán cho một số mục hoàn toàn nhỏ hơn hoặc bằng số lượng mục có thể được chèn ( ) thì hãy tiếp tục như bình thường nhưng sử dụng cùng giá trị của :Ti,j,kjkkTi,j,k=max{Ti,j1,k,Tiwj,j1,k+vj}
  • Bây giờ, nếu bạn phải tính cho một số mục lớn hơn số lượng mục có thể được chèn ( ) thì:Ti,j,kj>kTi,j,k=max{Ti,j1,k,Tiwj,j1,k1+vj}

Biểu thức đầu tiên phải rõ ràng. Lớp thứ hai hoạt động kể từ lớp thứ của bảng theo dõi sự kết hợp tốt nhất của các mục trong số thứ nhất theo yêu cầu ở trên.(k1)T(k1)(j1)

Việc triển khai hiệu quả thuật toán này không cần tính cho tất cả . Lưu ý rằng các mối quan hệ lặp lại trước đó liên quan đến lớp với và do đó, có thể xen kẽ giữa hai lớp liên tiếp (ví dụ: nếu bạn quan tâm đến giải pháp tối ưu với bạn chỉ cần sử dụng hai lớp liên tiếp: 0 và 1, 1 và 2, 2 và 3, 3 và 4 và bạn đã hoàn thành). Nói cách khác, thuật toán này chiếm gấp đôi bộ nhớ theo cách tiếp cận truyền thống dựa trên lập trình động và do đó, nó vẫn có thể chạy trong thời gian giả đa thức. k k ( k - 1 ) k = 4Ti,j,kkk(k1)k=4

Tuy nhiên, hãy lưu ý rằng đây không phải là giải pháp duy nhất! Và có một cái khác bạn có thể tìm thấy thanh lịch hơn. Trong các công thức trước, chúng tôi đã truy xuất giải pháp tối ưu bao gồm không quá mục trong số các mục đầu tiên là . Tuy nhiên, cần phải rõ ràng rằng điều này chính xác bằng chỉ bằng cách sử dụng bảng gốc !! tức là, có thể lấy ra giải pháp tối ưu với không quá mục bằng cách xem xét các giải pháp tối ưu với 1 mục, 2 mục, 3 mục, ...( j - 1 ) T i , j - 1 , k - 1 tối đa p = 0 , j - 1 { T i , p } k ( j - 1 ) k(k1)(j1)Ti,j1,k1maxp=0,j1{Ti,p}k(j1)các mục ... Để làm cho công thức này hoạt động, bạn cũng nên theo dõi số lượng các mục được xem xét trong mỗi giải pháp một phần để bạn sẽ cần hai số nguyên cho mỗi ô. Việc chiếm dụng bộ nhớ này dẫn đến chính xác các yêu cầu bộ nhớ tương tự của thuật toán được hiển thị ở trên (sử dụng chiều thứ ba ở dạng lớp )k .

Hi vọng điêu nay co ich,


Rất đáp ứng, cảm ơn bạn. Tôi đã có thể vượt qua nó trước bài viết của mình bằng cách triển khai chiều thứ 3.
dùng11536

Ouch, cảm ơn rất nhiều vì đã đóng câu hỏi và vui mừng khi biết rằng bạn thích câu trả lời. Để làm rõ ý tưởng của mình, tôi cũng đã thử triển khai thuật toán này trong Python. Nếu bạn quan tâm để có một cái nhìn về nó, hãy cho tôi biết và tôi sẽ vui vẻ đăng nó (hoặc gửi nó cho bạn). Chúc mừng,
Carlos Linares López

Giải thích tuyệt vời về vấn đề ba lô đa chiều. Tuy nhiên, tôi tự hỏi liệu chúng ta có trường hợp tương tự không nhưng với các phần tử k chính xác, chúng ta sẽ chỉ xem xét các giá trị được trả về bởi cột thứ k của chiều thứ 3. Nếu không có giá trị nào ở đó thì trả về 0.I Tôi không chắc liệu tôi có đúng không vì tôi vẫn chưa quen với lập trình động.
SteveIrwin

@ CarlosLinaresLópez câu trả lời tuyệt vời. Bạn có thể vui lòng chia sẻ kịch bản python không? Có thể đăng nó trên gist.github.com?
Saad Malik

1
Chao Carlos! Tôi đã đăng một câu hỏi tiếp theo để sử dụng công thức thay thế của bạn ở đây: Tìm kiếm các mục tốt nhất trong Knapsack 0/1 . Dù sao, tôi hy vọng bạn đang tận hưởng kỳ nghỉ của bạn!
Saad Malik
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.