D18-Acwing-复习背包问题

今天从后往前复习了,先巩固一下昨天的背包问题,毕竟昨天的代码是参考别人的,今天要自己写一遍。

2.01背包

1、还有一个状态f
2、直接用v[i]\w[i]接收就可以
3、j是从m开始的

N = 1010
n,m = map(int,input().split())
v = [0]*N
w = [0]*N
f = [0]*N
for i in range(n):
    v[i],w[i] = map(int,input().split())

for i in range(n):
    for j in range(m,v[i]-1,-1):
        f[j] = max(f[j],f[j-v[i]]+w[i])

print(f[m])

3.完全背包

f可化简为一维

N = 1010
f = [0]*N
v = [0]*N
w = [0]*N

n,m = map(int,input().split())
for i in range(n):
    v[i],w[i] = map(int,input().split())
    
for i in range(n):
    for j in range(v[i],m+1):
            f[j] = max(f[j],f[j-v[i]]+w[i])

print(f[m])
    

4.多重背包问题1–朴素版

居然按照自己的思路写出来了!!!说明理解了!!!开心!

N = 110
v = [0]*N
w = [0]*N
s = [0]*N
f = [[0]*N for _ in range(N)]

n,m = map(int,input().split())
for i in range(1,1+n):
    v[i],w[i],s[i] = map(int,input().split())
    
for i in range(1,1+n):
    for j in range(m+1):
        for k in range(s[i]+1):
            if k*v[i]<=j:
                f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i])
print(f[n][m])
            

5多重背包II——二进制优化

这个很不熟悉,其实具体原理就是把原来不同的物品根据个数划分为新的物品,然后用01背包,正好可以拼凑出原来的所有可能性

# 多重背包使用二进制进行优化
# 具体是先分好组,然后用01背包

N = 11010
M = 2010
v = [0]*N
s = [0]*N
w = [0]*N
f = [0]*N
n,m = map(int, input().split())
# 如何记录新的s[i]和与其对应的v[i]和w[i]。
# 通过一次次接收,而不是一下子接收
idx = 0
for _ in range(n):
    a,b,s = map(int,input().split())
    k = 1
    while k<=s:
        # 利用idx给物品重新编号,不同数量的同一物品,看做不同物品。
        idx+=1
        v[idx] = a*k
        w[idx] = b*k
        s -= k
        k *= 2
    if s>0:
        idx += 1
        v[idx] = a*s
        w[idx] = b*s
n = idx
for i in range(1,1+n):
    for j in range(m,v[i]-1,-1):
        f[j] = max(f[j],f[j-v[i]]+w[i])
print(f[m])
    

9分组背包

非常混乱。题意理解错了,每组只能选一种,每种也只能选一个。
这是自己写的

N = 110
v = [[0]*N for _ in range(N)]
w = [[0]*N for _ in range(N)]
s = [0]*N
f = [[0]*N for _ in range(N)]

n,m = map(int,input().split())

for i in range(1,1+n):
    s[i] = int(input())
    for j in range(1,s[i]+1):
        v[i][j],w[i][j] = map(int,input().split())
# 第i组物品
for i in range(1,1+n):
    # 选其中的第k个
    for k in range(1,s[i]+1):
        # 背包体积为j
        for j in range(1+m):
            nums =0
            if j>=v[i][k]*nums:
                f[i][j] = max(f[i][j],f[i-1][j-v[i][k]*nums]+w[i][k]*nums)
                nums += 1
            else:
                break
print(f[n][m])
        

嗯,理解题意后,又自己写了一下,效果还不错。

N = 110
v = [[0]*N for _ in range(N)]
w = [[0]*N for _ in range(N)]
s = [0]*N
f = [0]*N

n,m = map(int,input().split())

for i in range(1,1+n):
    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,1+n):
    for j in range(m,-1,-1):
        for k in range(1,s[i]+1):
            if j>=v[i][k]:
                f[j] = max(f[j],f[j-v[i][k]]+w[i][k])
print(f[m])
            
        
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值