python背包问题总结

1. 0/1背包

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

2. 完全背包

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

3. 多重背包(二进制优化)

    W = [None]
    V = [None]

    for i in range(1,n+1):
        w,v,num = map(int,input().strip().split())
        k = 1
        while k <= num:
            num = num - k
            W.append(k*w)
            V.append(k*v)
            k = k*2

        if num > 0:
            W.append(num*w)
            V.append(num*v)       

    dp = [0 for i in range(m+1)]
    for i in range(1,len(W)):
        for j in range(m,W[i]-1,-1):
            dp[j] = max(dp[j],dp[j-W[i]]+V[i])

4. 一维费用背包(求最小值)   拿到价值m的最小重量

dp = [inf for i in range(m+1)]
dp[0] = 0
for i in range(1,n+1):
    for j in range(m,0,-1):
        if j < v[i]:
            dp[j] = min(dp[j],w[i])
        else:
            dp[j] = min(dp[j],dp[j-v[i]]+w[i])

5. 二维费用背包

    V = [None for i in range(n+1)]
    M = [None for i in range(n+1)]
    W = [None for i in range(n+1)]

    for i in range(1,n+1):
        V[i],M[i],W[i] = map(int,input().strip().split())

    dp = [[0 for j in range(m+1)] for i in range(v+1)]
    for k in range(1,n+1):
        for i in range(v,V[k]-1,-1):
            for j in range(m,M[k]-1,-1):
                dp[i][j] = max(dp[i][j],dp[i-V[k]][j-M[k]]+W[k])
    print(dp[v][m])

6. 背包计数,在背包容量为m时,拿到最大价值的方案数      ★★★

def f(n,m):
    ans = [1 for j in range(m+1)]
    dp = [0 for j in range(m+1)]

    for i in range(1,n+1):
        w,v = map(int,input().strip().split())
        for j in range(m,w-1,-1):
            if dp[j] < dp[j-w]+v:
                ans[j] = ans[j-w]
            elif dp[j] == dp[j-w]+v:
                ans[j] = (ans[j]+ans[j-w])%(10**9+7)
                
            dp[j] = max(dp[j],dp[j-w]+v)

    print(ans[m])

7. 分组背包              ★

    W = [[] for i in range(n+1)]
    V = [[] for i in range(n+1)]
    num = [0 for i in range(n+1)]
    
    for i in range(1,n+1):
        num[i] = int(input().strip())
        for j in range(num[i]):
            w,v = map(int,input().strip().split())
            W[i].append(w)
            V[i].append(v)

    dp = [0 for j in range(m+1)]
    for i in range(1,n+1):
        for j in range(m,0,-1):
            for k in range(num[i]):
                if j >= W[i][k]:
                    dp[j] = max(dp[j],dp[j-W[i][k]]+V[i][k])
    print(dp[m])

8. 混合背包

    W = [None]
    V = [None]

    for i in range(1,n+1):
        w,v,num = map(int,input().strip().split())
        if num == -1:
            num = 1
        elif num == 0:
            num = m//w

        k = 1
        while k <= num:
            num = num - k
            W.append(k*w)
            V.append(k*v)
            k = k * 2
        if num > 0:
            W.append(num*w)
            V.append(num*v)

    dp = [0 for i in range(m+1)]
    for i in range(1,len(W)):
        for j in range(m,W[i]-1,-1):
            dp[j] = max(dp[j],dp[j-W[i]]+V[i])
    print(dp[m])

9. 背包问题求具体方案         ★★★

    W = [None for i in range(n+1)]
    V = [None for i in range(n+1)]
    dp = [[0 for j in range(m+1)] for i in range(n+2)]

    for i in range(1,n+1):
        W[i],V[i] = map(int,input().strip().split())

    for i in range(n,0,-1):       #注意,此处逆序
        for j in range(m,0,-1):
            dp[i][j] = dp[i+1][j]
            if j >= W[i]:
                dp[i][j] = max(dp[i][j],dp[i+1][j-W[i]]+V[i])

    now_w = m
    for i in range(1,n+1):
        if now_w <= 0:
            break
        if now_w >= W[i] and dp[i][now_w] == dp[i+1][now_w-W[i]]+V[i]:
            print(i,end = ' ')
            now_w = now_w - W[i] 

10. 有依赖的背包     ★★

def dfs(x):
    global W,V,dp,m
    for j in range(W[x],m+1):
        dp[x][j] = V[x]

    for i in range(len(son[x])):
        y = son[x][i]
        dfs(y)
        for j in range(m,W[x]-1,-1):
            for k in range(j-W[x]+1):
                dp[x][j] = max(dp[x][j],dp[x][j-k]+dp[y][k])
        

def f(n,m):
    global son,root,dp

    for i in range(1,n+1):
        W[i],V[i],f = map(int,input().strip().split())
        if f == -1:
            root = i
        else:
            son[f].append(i)
    dfs(root)
    print(dp[root][m])
            
        
if __name__ == '__main__':
    n,m = map(int,input().strip().split())
    root = None
    son = [[] for i in range(n+1)]
    W = [None for i in range(n+1)]
    V = [None for i in range(n+1)]
    dp = [[0 for j in range(m+1)] for i in range(n+1)]
    f(n,m)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值