一、背包問題
1、問題描述
2、引進動態規划表格來解釋問題
這個表格中
背包容量:最大值是輸入給定,
物品編號:0、表示前0個物品最佳組合;
1、表示前1個物品最佳組合;(所以這里是不是要求物品編號有一定的順序??)
2、表示前2個物品最佳組合;
空白格子:最佳組合所能產生的價值
3、往動態規划表中填入價值數據
a、物品編號為0,前0物品組合(沒有物品),不管背包容量多大,價值為0。
b、背包容量為0,沒有物品可以裝得下,價值為0
c、背包容量為1,物品編號為1:
(1)如果裝1號物品,價值改變;
(2)如果不裝1號物品,價值和前0號物品價值想同;
由於裝不下1號物品,所有只能選擇(2)
d、背包容量為2,物品編號為1:
(1)判斷當前背包容量能否裝下當前的物品; 能
(2)如果能:判斷裝下該物品后總價值 和 不裝該物品的總價值 那個更大
如果不能:不裝該物品,總價值和前一行的總價值相等
d、背包容量為3,物品編號為2:(1)判斷當前背包容量能否裝下當前的物品; 能
(2)如果能:判斷裝下該物品后總價值 (4) 和 不裝該物品的總價值 (3) 哪個更大
如果不能:不裝該物品,總價值和前一行的總價值相等
最后,取總價值大的 4
e、其他空白依次類推,不做詳述。。。。
代碼實現:
1、數據輸入:
n = int(input()) w = list(map(int,input().split())) v = list(map(int,input().split())) c = int(input()) """ 測試數據: n = 4 物品的數量, w = [2, 3, 4, 5] 每個物品的重量, v = [3,4, 5, 6 ] 每個物品的價值, c = 8 書包能承受的重量, """
2、動態規划表的繪制
value = [[0 for j in range(c + 1)] for i in range(n + 1)] #構造一個dp表 for i in range(1, n + 1): for j in range(1, c + 1): if (w[i-1]>j): #如果當前物品質量大於當前背包容量 value[i][j] = value[i-1][j] #不裝改物品,總價值和前一個總價值相等 else: #如果可以裝下該物品,比較 不裝該物品的價值 和 裝下該物品后的價值那個更大,取大值。 value[i][j] = max(value[i-1][j],value[i-1][j-w[i-1]]+v[i-1]) for x in value: print(x)
4、背包問題回溯
理解:根據動態規划表的構建,如果當前物品被放入背包中,則當前總價值大於前一行的總價值。
所以可以根據兩行總價值 來判斷 當前物品是否在背包中。
代碼實現:
print('最大價值為:', value[n][c]) x = [False for i in range(n)] j = c for i in range(n, 0, -1): if value[i][j] > value[i - 1][j]: #判斷當前價值與前一行的價值 x[i - 1] = True #當前物品置一 j -= w[i - 1] #背包容量里面減去相應的物品容量 print('背包中所裝物品為:') for i in range(n): if x[i]: print('第', i+1, '個,', end='')