為媽媽下次廚:加加調味組合 4 瓶 14.8 元好價(商超 9.9 元/瓶)
阿新 • • 發佈:2022-05-08
title: 0-1揹包問題
date: 2022-05-11 11:02:33
tags: 演算法
0-1揹包問題
蠻力列舉法
依次列出所有可能情況
n表示有n個商品, C表示容量
其中顏色相同的是需要重複計算的
帶備忘的遞迴
為了解決這個問題->需要大量計算重複的過程,這個時候我們可以引進一個“備忘錄”,如果遇到需要重複計算的式子的話,我們可以直接重備忘錄中獲取。
虛擬碼的實現:
KnapsackMR(i, c)
輸入:商品集合{1,...,i},揹包容量c
輸出:最大總價格P[i, c]
if(c < 0) then 容量為零 返回負無窮
return 負無窮
end
if i ≤ 0 then 如果商品的個數小於零的話,返回零
return 0
end
if P[i, c] ≠ NULL then 如果備忘錄中有這個的話就不用計算 直接返回即可
return P[i, c]
end
P1 = KnapsackMR(i-1, c-vi)
P2 = KnapasckMR(i-1, c)
p[i, c] <= max{P1 + pi, P2}
return P[i, c]
計算順序:
為了能夠不遞推,直接求解P[i,c],這就需要我們事先把備忘錄表,全部填寫上去
p[i,c]確定的方法需要讓p[i-1, c]和p[i-1,c-vi]+pi 相比較,選取其中較大的哪一個
程式碼實現
# 揹包問題 # 第一個引數為商品數量 # 第二個引數為揹包容量 # 第三個引數為價格表容量表 def memo_rec_matrix(num_commodity, size_knapsack, Price): # 建立備忘錄格式 memo = [ [ [] for i in range(size_knapsack+1)] for m in range(num_commodity+1)] # 建立追蹤表格 0 表示不選擇該商品,1表示選擇該商品 rec = [ [ [] for i in range(size_knapsack+1)] for m in range(num_commodity+1)] # 初始化備忘錄 和 追蹤表格 for m in range(size_knapsack+1): memo[0][m] = 0 rec[0][m] = 0 for m in range(num_commodity+1): memo[m][0] = 0 rec[m][0] = 0 # 當我們商品數量為1 - num_commodity 的時候各種情況 for i in range(1, num_commodity+1): # 當揹包容量為1-size_knapsck的時候的各種情況 for m in range(1, size_knapsack+1): # 如果揹包容量小於第i個商品的體積的話, # 就讓memo陣列對應的 商品數量i行 和 揹包容量m列的位置 等於上一行的這一列的容量, # 因為上一行這一列的容量是 這個容量是沒有i個商品的容量最大值, 並且設定rec[i][m]這個位置為零 if m < Price[0][i-1]: memo[i][m] = memo[i-1][m] rec[i][m] = 0 # 如果揹包容量大於第i個商品的體積的話,需要進行判斷 else: # 如果加上第i個商品之後的價值 小於沒有加上該商品的價值的話, # 那麼就把該位置設定成沒有加上第i個商品的時候價值 # 把rec該位置的座標賦值為0 因為沒有選擇了該商品 if memo[i-1][m] > memo[i-1][m-Price[0][i-1]]+Price[1][i-1]: memo[i][m] = memo[i-1][m] rec[i][m] = 0 # 如果大於的話直接賦值就行 # 把rec該位置的座標賦值為1 因為選擇了該商品 else: memo[i][m] = memo[i-1][m-Price[0][i-1]]+Price[1][i-1] rec[i][m] = 1 return memo, rec # 追蹤陣列 def track(rec, price): rec_num_line = len(rec)-1 rec_num_column = len(rec[0])-1 while(True): # 迴圈條件 商品數量為0 if rec_num_line == 0: break elif rec[rec_num_line][rec_num_column] == 0: rec_num_line -= 1 else: print(rec_num_line) rec_num_line -= 1 rec_num_column -= price[0][rec_num_line] price = [ [10,3,4,5,4], # 體積 [24,2,9,10,9] # 價格 ] # 商品數量 num_commodity = 5 # 揹包容量 size_knapsack = 13 memo, rec = memo_rec_matrix(num_commodity,size_knapsack,price)