python背包问题并行_背包问题九讲python3实现
背包九講是動態規劃思想的經典呈現,找了許久沒有完整的python3實現,趁機總結一下。
1、0-1背包問題
二維DP數組解法:
# n, v分別代表物品數量,背包容積
n, v = map(int, input().split())
# w為物品價值,c為物品體積(花費)
w, cost = [0], [0]
for i in range(n):
cur_c, cur_w = map(int, input().split())
w.append(cur_w)
cost.append(cur_c)
#該初始化代表背包不一定要裝滿
dp = [[0 for j in range(v+1)] for i in range(n+1)]
for i in range(1, n+1):
for j in range(1, v+1): #可優化成 for j in range(cost[i], v+1):
if j < cost[i]:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-cost[i]]+w[i])
print(dp[n][v])
時間復雜度:O(VN),不能再優化,但對空間復雜度可以進行優化,使用一維數組。
一維DP數組解法:
# n, v分別代表物品數量,背包容積
n, v = map(int, input().split())
# w為物品價值,c為物品體積(花費)
w, cost = [0], [0]
for i in range(n):
cur_c, cur_w = map(int, input().split())
w.append(cur_w)
cost.append(cur_c)
#該初始化代表背包不一定要裝滿
dp = [0 for j in range(v+1)]
for i in range(1, n+1):
#注意:第二層循環要逆序循環
for j in range(v, 0, -1): #可優化成 for j in range(v, cost[i]-1, -1):
if j >= cost[i]:
dp[j] = max(dp[j], dp[j-cost[i]]+w[i])
print(dp[v])
值得注意的是:第二層循環中對背包容量 V 要逆序遍歷,保證 dp[j-cost[i]] 是絕對不包含當前物品的選擇。參考《背包九講》
2、完全背包問題
一維DP數組解法:
只需要基于 0-1背包問題 的一維DP解法修改一行代碼即可!!!
# n, v分別代表物品數量,背包容積
n, v = map(int, input().split())
# w為物品價值,c為物品體積(花費)
w, cost = [0], [0]
for i in range(n):
cur_c, cur_w = map(int, input().split())
w.append(cur_w)
cost.append(cur_c)
#該初始化代表背包不一定要裝滿
dp = [0 for j in range(v+1)]
for i in range(1, n+1):
#只需要將0-1背包一維DP解法中的二層循環改為順序循環
for j in range(1, v+1):
if j >= cost[i]:
dp[j] = max(dp[j], dp[j-cost[i]]+w[i])
print(dp[v])
時間復雜度:O(VN)
為什么順序遍歷就能解決問題?
對于當前物品 i ,要么不拿為dp[j],要么拿為dp[j-cost[i]]+w[i],而dp[j-cost[i]]代表之前的狀態中,也包含拿過物品 i 的狀態,這樣就包含了多次拿取物品 i 的情況。
優化:
3、多重背包問題
最直接的解法:
將每件物品的件數 Mi 作為獨立的物品,這樣時間復雜度為O(V sum(Mi))
# n, v分別代表物品數量,背包容積
n, v = map(int, input().split())
# w為物品價值,c為物品體積(花費)
w, cost, s = [0], [0], [0]
for i in range(n):
cur_c, cur_w,cur_s= map(int, input().split())
w += [cur_w]*cur_s
cost += [cur_c]*cur_s
n = len(w)-1
#該初始化代表背包不一定要裝滿
dp = [0 for j in range(v+1)]
for i in range(1, n+1):
for j in range(v, cost[i]-1, -1):
if j >= cost[i]:
dp[j] = max(dp[j], dp[j-cost[i]]+w[i])
print(dp[v])
優化:
class Solution:
# 0-1背包問題的寫法
def max_value(self, n, m, v, w):
dp = [0] * (m + 1)
for i in range(1, n + 1):
for j in range(m, v[i] - 1, -1):
dp[j] = max(dp[j], dp[j - v[i]] + w[i])
return dp[-1]
if __name__ == '__main__':
import sys
n, m = map(int, input().split())
lines = sys.stdin.readlines()
v, w = [0], [0]
n = 0
for line in lines:
line = list(map(int, line.split()))
k = 1
while k <= line[2]: # 假設line[2]=13,k取1,2,4之后,line[2] = 6 < k = 8 退出循環
v.append(k * line[0])
w.append(k * line[1])
line[2] -= k
k *= 2
n += 1 # 物品總數加1
if line[2]:
v.append(line[2] * line[0])
w.append(line[2] * line[1])
n += 1
print(Solution().max_value(n, m, v, w))
作者:polaris
鏈接:https://www.acwing.com/solution/acwing/content/3988/
總結
以上是生活随笔為你收集整理的python背包问题并行_背包问题九讲python3实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机动目标跟踪——Singer模型
- 下一篇: 制作U盘DOS启动盘详细教程及工具,及D