動態規劃求解01揹包相關的基本問題

2021-06-06 03:39:26 字數 2715 閱讀 7033

揹包問題是經典問題,網上已經提供了很多優秀的解法,這裡摘錄動態規則的方法,同時順便把揹包相關的變形問題也一些闡述。

問題:1. 經典揹包問題:給定乙個載重量為m,n個物品,其重量為wi,價值為vi,1<=i<=n,要求:把物品裝入揹包,並使包內物品價值最大。

2. 變形:要求裝入的物品重量最大?(問題很簡單,但請先別bs我)

3. 變形:要求裝入的物品重量剛好等於揹包的承重?換一種說法就是:n個數里挑出任意個數,使這些數的和等於某個值m。

4. 變形:n個數里挑出任意個數,使這些數的和最接近m,即和與m的差的絕對值最小。

問題1請參考:

核心思想如下:

在0/1揹包問題中,物體或者被裝入揹包,或者不被裝入揹包,只有兩種選擇。

迴圈變數i,j意義:前i個物品能夠裝入載重量為j的揹包中

(n+1)*(m+1)陣列value意義:value[i][j]表示前i個物品能裝入載重量為j的揹包中物品的最大價值

若w[i]>j,第i個物品不裝入揹包

否則,若w[i]<=j且第i個物品裝入揹包後的價值》value[i-1][j],則記錄當前最大價值(替換為第i個物品裝入揹包後的價值)

問題2:很簡單。可以將這裡的重量看成是問題1的價值。之所以寫出來是為了方便分析問題4.

問題3:採用類似於問題1的方法,對n個數(無序),以n[i]表示第i個數。構造乙個(n+1)行(m+1)列的矩陣(+1行與列是為了下標好計算)。

關鍵點:對於某個m=j。給定序列n[1~i],組成和為 j 的子集u中若包含n[i],則n[1~i-1]肯定能夠組成和為j-n[i]。

如圖所示,為了簡單起見,令n個數正好是1到n遞增(不需要是有序的,僅為舉例方便),令m=6。

矩陣的值v[i][j]有三種表示方法:

1. y。表示n[i] =  j。這樣,由n[1~i]個數,和為j的一種挑法就是只挑出n[i]本身。

2. x。表示由n[1~i]個數構成和為j的集合中,任一集合都沒有n[i] 。

3. 矩陣的另乙個位址,表示n[i] 可以構成和為j的集合中的乙個元素,而其它的元素需要到矩陣的另乙個位址中繼續尋找。

演算法描述如下:

1. 若當前n[i]=j ,則v[i][j]標記為 「y」;

2. 判斷n[i]是否屬於加和集合。需要看n[1~i-1]是否可以構成 j-n[i]。判斷的方法就是對第j-n[i]列,從行號為i-1開始直到0,看是否有值不為 「x」。查詢的結果有兩種可能:

a. 沒有,即全為x。表示n[i]不可能屬於加和集合中的一分子,故把v[i][j]標記為 「x」;

b. 有。記錄轉轉位址。

當遍歷結束後。採用回溯可以得到所有構成的路徑。這時,標記為「y」的矩陣值即是路徑回溯的終點。n個數

\m 0

1 2

3 4

5 6

0 yx

x xx x

x 1x y

x x

x x

x 2

x x

y(1,

1)x

x x

3 x

x x

y(1,

1)(2

,2)(

2,3)

4 x

x x

x y(

1,1)

(2,2

)5 x

x xx x

y(1,1

)舉例分析:

初始化第0行與第0列。

看v[1][1],由於有n[1]=1,故標記為y。

看v[2][3],考慮n[2]=2是否是構成和為3的乙個元素,則需要看由元素集合n[1~i-1],是否可以構成j-n[i],即{1}是否可以構成和為1。從查詢v[1][1]找到v[0][1],發現v[1][1]標記為y,表示可以構成,所以v[2][3]記錄位址{1,1}。

看v[3][6],同理,若n[3]=3能構成和為6的乙個元素的話,就要求n[1~2]能構成和為3,查詢發現v[2][3]的值不是「x」,表示上述假設成立,因此記錄(2,3).

當遍歷結束後,回溯尋找和為m的方法,這裡m=6.

首先發現v[5][6],確定5,跳轉到v[1][1],為y,結束,集合為{1,5}. 同列往上繼續走到v[0][1],為x,結束。

往上走到v[4][6], 確定4,跳轉到v[2][2],為y,結束,集合為{2,4}. 同列往上繼續走到v[1][2]與v[0][2],皆為x,結束。

往上走到v[3][6],確定3,跳轉到v[2][3],確定2,跳轉到v[1][1],確定1,集合為{1,2,3}. 同列往上繼續走到v[0][1],為x; 回退,發現v[1][3]也為x,結束。

往上走到v[1~2][6],都沒有構成集合,結束。

這裡為什麼在找到一條路徑後,還需要繼續在同列往上走呢?這是為把所有組合都成找到,請自行分析m=7的情況,如果不往上走,將只能找到{2,5}與{3,4},而少一組{1,2,4}.而最後一組{1,2}又構成了3.

問題4:

運用問題2或3的解法可解。運用問題2來解比較快:假設揹包最大承重為m,解一次問題2,即可得到加和小於m,且最接近m的的值,設為s。由於求的是絕對值最小,所以有可能可以找到加和大於m的解,而這個解必然屬於揹包大小為m+1到m+(m-s)-1 範圍內,問題2的解。舉例如下:假設m=6,求得s=3,目前的絕對值差為3,而如果正確的解是s>m的情況,那麼該解必然屬於揹包大小為7到8當中的最優解。即,最壞情況下,給乙個大小為8的包,能裝滿,則這時和的絕對值差為2,比原來優,而揹包給的再大已經沒有意義。

01揹包問題 動態規劃求解

時間限制 1 sec 記憶體限制 128 mb 提交 48 解決 17 給定n種物品和乙個揹包,物品i的重量是wi,其價值為vi,問如何選擇裝入揹包的物品,使得裝入揹包的物品的總價值最大?在選擇裝入揹包的物品時,對每種物品i只能有兩種選擇,裝入或者不裝入,不能裝入多次,也不能部分裝入。第一行輸入物品...

0 1揹包問題,動態規劃求解

1.什麼是0 1揹包問題?有n個物品,它們有各自的體積和價值,現有給定容量的揹包,如何讓揹包裡裝入的物品具有最大的價值總和?舉例int v 每個物品對應的價值 int w 每個物品對應的重量 int bag 10 揹包最大承重10 0 1揹包問題 public static void main st...

用動態規劃求解0 1揹包問題

0 1揹包問題描述 有n件物品和乙個重量為m的揹包。每種物品均只有一件 第i件物品的重量是w i 價值是p i 求解將哪些物品裝入揹包可使價值總和最大。動態規劃的基本思想 將乙個問題分解為子問題遞迴求解,且將中間結果儲存以避免重複計算。通常用來求最優解,且最優解的區域性也是最優的。求解過程產生多個決...