分组背包问题

9. 分组背包问题 - AcWing题库

N=105
#f[i][j] 表示从前i件物品中选,体积<=j,属性为价值max
#分割点:不选取第i件物品 f[i-1][j]
#选取第i件物品k件 f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+w[i]*k)
#                 f[i][j-v[i]]=max(f[i-1][j-v[i]],f[i-1][j-v[i]-k*v[i]]+w[i]*k)
f=[[0 for i in range(N)]for i in range(N)]
v=[[0 for i in range(N)]for i in range(N)]
w=[[0 for i in range(N)]for i in range(N)]
s=[0 for i in range(N)]#每组个数
n,v1=map(int,input().split())
for i in range(1,n+1):
    s[i]=int(input())
    for j in range(1,s[i]+1):
        v[i][j],w[i][j]=map(int,input().split())

for i in range(1,n+1):
    for j in range(v1+1):
        f[i][j]=f[i-1][j]
        for k in range(1,s[i]+1):#第i组的数量
            if j>=v[i][k]:
                f[i][j]=max(f[i][j],f[i-1][j-v[i][k]]+w[i][k])
print(f[n][v1])
        

空间优化版

N=105
#f[i][j] 表示从前i件物品中选,体积<=j,属性为价值max
#分割点:不选取第i件物品 f[i-1][j]
#选取第i件物品k件 f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+w[i]*k)
#                 f[i][j-v[i]]=max(f[i-1][j-v[i]],f[i-1][j-v[i]-k*v[i]]+w[i]*k)
f=[0 for i in range(N)]
v=[[0 for i in range(N)]for i in range(N)]
w=[[0 for i in range(N)]for i in range(N)]
s=[0 for i in range(N)]#每组个数
n,v1=map(int,input().split())
for i in range(1,n+1):
    s[i]=int(input())
    for j in range(1,s[i]+1):
        v[i][j],w[i][j]=map(int,input().split())

for i in range(1,n+1):
    for j in range(v1,-1,-1):
        for k in range(1,s[i]+1):#第i组的数量
            if j>=v[i][k]:
                f[j]=max(f[j],f[j-v[i][k]]+w[i][k])
print(f[v1])
        

一维空间优化逆序问题

假如枚举到:i = 3, j = 8, v[3] = 5, w[3] = 1

二维:dp[3][8] = max(dp[2][8], dp[2][3] + w[3])   此时的dp[2][8]和dp[2][3]都是上一轮的状态值

一维:dp[8] = max(dp[8], dp[3] + w[3])      我们要保证dp[8]和dp[3]都是上一轮的状态值

按照逆序的顺序,一维dp数组的更新顺序为:dp[8], dp[7], dp[6], ... , dp[3]

也就是说,在本轮更新的值,不会影响本轮中其他未更新的值!较小的index对应的状态是上一轮的状态值!

如果按照顺序进行更新,dp[3] = max(dp[3], dp[0] + w[0]),对dp[3]的状态进行了更新,那么在更新dp[8]时,用到的dp[3]就不是上一轮的状态了,不满足动态规划的要求。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值