小学生蓝桥杯Python闯关 | 1270:【例9.14】混合背包

118 阅读2分钟

学习Python从娃娃抓起!记录下蓝桥杯Python学习和备考过程中的题目,记录每一个瞬间。

附上汇总贴:小学生蓝桥杯Python闯关 | 汇总_COCOgsta的博客-CSDN博客


【题目描述】

一个旅行者有一个最多能装V公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn。有的物品只可以取一次(01背包),有的物品可以取无限次(完全背包),有的物品可以取的次数有一个上限(多重背包)。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

【输入】

第一行:二个整数,M(背包容量,M<=200),N(物品数量,N<=30);

第2...N+1行:每行三个整数Wi,Ci,Pi,前两个整数分别表示每个物品的重量,价值,第三个整数若为0,则说明此物品可以购买无数件,若为其他数字,则为此物品可购买的最多件数(Pi)。

【输出】

仅一行,一个数,表示最大总价值。

【输入样例】

10 3

2 1 0

3 3 1

4 5 4

【输出样例】

11

【代码详解】

M, N = [int(i) for i in input().split()]
Wi = [0]
Ci = [0]
Pi = [0]
vis = [0]

dp = [0 for i in range(M+1)]

for i in range(1, N+1):
    ls = [int(i) for i in input().split()]
    w = ls[0]
    c = ls[1]
    p = ls[2]
    if p == 0:
        vis.append(1)
        Wi.append(w)
        Ci.append(c)
        continue
    if p == 1:
        vis.append(0)
        Wi.append(w)
        Ci.append(c)
        continue
    j = 1
    while j <= p:
        p -= j
        vis.append(0)
        Wi.append(j*w)
        Ci.append(j*c)
        j <<= 1
    if p:
        vis.append(0)
        Wi.append(p*w)
        Ci.append(p*c)
        Pi.append(0)
for i in range(1, len(Wi)):
    if (vis[i] == 1): #用完全背包处理
        for j in range(Wi[i], M+1):
            dp[j] = max(dp[j], dp[j-Wi[i]]+Ci[i])
    else: #用01背包处理
        for j in range(M, Wi[i]-1, -1):
            dp[j] = max(dp[j], dp[j-Wi[i]]+Ci[i])

print(dp[M])

【运行结果】

10 3 
2 1 0
3 3 1
4 5 4
11