問題描述:
給定n個物品和乙個容量為capacity的揹包,物品i的大小為w[i],物品i的價值為v[i]。如何選擇物品裝入揹包,使揹包中物品價值最大?
思路分析:動態規劃
動態規劃陣列:dp[i][j]表示從前i個物品中挑選物品放入容量為j的揹包中所得到的揹包的總價值。
則面對第i個物品,有兩種選擇:放與不放。
①當目前揹包容量大於等於當前物品的大小時,可以放,也可以不放,所以要選擇兩者的最大值。
其中,dp[i-1][j-w[i]]是判斷完前(i-1)個物品後的揹包內的總價值,加上第i個物品的價值v[i],即為當前揹包價值
②當前揹包容量小於當前物品大小時,當前物品一定放不下,所以dp[i][j] = dp[i-1][j]。
狀態轉移方程為:
**實現:
①填寫動態規劃表,dp二維陣列初始化為0。
# 填寫動態規劃表
for i in range(1, n + 1):
for j in range(1, capacity + 1):
# 如果揹包容量小於當前物品大小,則不放
if j < w[i]:
dp[i][j] = dp[i - 1][j]
# 反之,可以放也可以不放,取兩者的最優解
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i])
②回溯找到最優解的情況
填完動態規劃表之後,能夠得到最優解,但是還不知道具體的最優解情況,即要選擇哪些物品,所以要回溯找出最優解的組成。
和填寫動態規劃表相反:
如果dp[i][j] == dp[i-1][j],說明第i個物品放與不放對揹包價值沒有影響,所以回到前一狀態,即dp[i-1][j]的狀態。
如果dp[i][j] != dp[i-1][j]且dp[i][j] = dp[i-1][j-w[i]]+v[i],說明第i個物品放入了揹包中,所以回到dp[i-1][j-w[i]]這一狀態。
直到i==0,回溯到頂端停止。
在回溯過程中,維護乙個res陣列,大小為物品的個數,記錄對應的物品是否放入揹包中。對於放入揹包中的物品,陣列對應位置的值置為1;沒有放入,就置為0。
# 回溯找到最優解情況存放到res陣列中,0:不放;1:放
def find(i, j, res):
if i > 0:
# 沒有放入第i個物品
if dp[i][j] == dp[i - 1][j]:
# 最優解陣列當前位置標記為0
res[i] = 0
# 遞迴
find(i - 1, j, res)
# 放入第i個物品
elif j - w[i] >= 0 and dp[i][j] == dp[i - 1][j - w[i]] + v[i]:
res[i] = 1
find(i - 1, j - w[i], res)
③完整**
w = [0, 2, 3, 4, 5] # 物品大小
v = [0, 3, 4, 5, 6] # 每個物品對應的價值
n, capacity = 4, 8
# dp[i][j]表示當前揹包容量為j,前i個物品的價值
# 初始化dp陣列為0
dp = [[0 for j in range(capacity + 1)] for i in range(n + 1)]
# 存放最優解情況
res= [0 for i in range(n + 1)]
# 填寫動態規劃表
for i in range(1, n + 1):
for j in range(1, capacity + 1):
# 如果揹包容量小於當前物品大小,則不放
if j < w[i]:
dp[i][j] = dp[i - 1][j]
# 反之,可以放也可以不放,取兩者的最優解
else:
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i])
# 回溯找到最優解情況存放到res陣列中,0:不放;1:放
def find(i, j, res):
if i > 0:
# 沒有放入第i個物品
if dp[i][j] == dp[i - 1][j]:
# 最優解陣列當前位置標記為0
res[i] = 0
# 遞迴
find(i - 1, j, res)
# 放入第i個物品
elif j - w[i] >= 0 and dp[i][j] == dp[i - 1][j - w[i]] + v[i]:
res[i] = 1
find(i - 1, j - w[i], res)
# 呼叫回溯函式
find(n, capacity, res)
# 輸出物品選擇情況
print(res)
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...
揹包問題 01揹包
有n件物品和乙個容量為v的揹包。第i件物品的重量是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。01揹包中的 01 就是一種物品只有1件,你可以選擇放進去揹包即1,也可以選擇不放入揹包中即0。include include using namespace std const int ...
揹包問題(01揹包)
1085 揹包問題 在n件物品取出若干件放在容量為w的揹包裡,每件物品的體積為w1,w2 wn wi為整數 與之相對應的價值為p1,p2 pn pi為整數 求揹包能夠容納的最大價值。input 第1行,2個整數,n和w中間用空格隔開。n為物品的數量,w為揹包的容量。1 n 100,1 w 10000...