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]就不是上一轮的状态了,不满足动态规划的要求。