文章目录
经典01背包
问题描述:
给定 n 件物品,物品的重量为 w[i],物品的价值为 v[i]。现挑选物品放入背包中,假定背包能承受的最大重量为 c,问应该如何选择装入背包中的物品,使得装入背包中物品的总价值最大?
首先输入共n个物品,一个容量为v的背包,n和v没有协同关系,只是制约关系
再输入[各物品重量,各物品价值]
分别存入重量数组与价值数组
本题以n,v=4,5 ,输入(1,2)(2,4)(3,4)(4,5)为例
4 5
1 2
2 4
3 4
4 5
总代码 and 模板
遍历:先物品 后背包容量
因为要先开始物品,所以dp初始化:行是物品,行中的列是背包容量
N,V=map(int,input().split()) #物品数量、背包容量
weight=[0]
val=[0]
for i in range(N):
wi,vi=map(int,input().split())
weight.append(wi)
val.append(vi)
dp = [[0]*(V+1) for _ in range(N+1)] #N行,V列
for i in range(1,N+1):#先物品、后背包容量
for j in range(1,V+1):
if j-weight[i]<0:
dp[i][j]=dp[i-1][j]
else:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+val[i])
print(dp[N][V])
细节
注意是先重量,后价值。不要弄混了而加错了集合
N,V = map(int,input().split())
weight = []
val = []
for _ in range(N):
wi,vi = map(int,input().split())
weight.append(wi)
val.append(vi)
weight=[1,2,3,4]
value = [ 2,4,4,5]
初始化dp数组:
dp = [ [0]*(V+1) for _ in range(N+1) ]
因为存在【没有物品,但有容量】与【有物品,容量不够】的情况,所以保留0数组
又因需要到达n,则range(N+1)
则五行六列
行:前4件物品
列:容量为1到5的书包
遍历背包,遍历
{ weight[i] , value[i] }与dp之间的关系:
dp通过 【i-1,{ 减weight[i] } + value[i]} 】 到达 下一个dp
for i in range(1,N+1):
for w in range(1,V+1):
if w<weight[i-1]: #给的容量不够装下 该重量的物品,则到前一件里找适不适合
dp[i][w] = dp[i-1][w]
#若装的下且取到了i:
#dp[i][w]
else:
dp[i][w] = max(dp[i-1][w-weight[i-1]]+val[i-1], dp[i-1][w])
为什么是i-1呢?因为保留0的原因,导致i相比 与 相对应的 value大1,
采药问题
输入:
70 3
71 100
69 1
1 2
输出:
3
T,M=map(int,input().split())#时间、药草数
time=[0]
val=[0]
for i in range(M):
ti,vi=map(int,input().split())
time.append(ti)
val.append(vi)
dp=[[0]*(T+1) for i in range(M+1)]
for i in range(1,M+1):
for j in range(1,T+1):
if j<time[i]:
dp[i][j]=dp[i-1][j]
else:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-time[i]]+val[i])
print(dp[M][T])