Mary的烦恼

文章介绍了如何使用动态规划解决01背包问题,其中给出了两种不同的Python实现方法,一种是二维数组的状态转移,另一种是一维数组的状态更新。这两种方法的目标都是在不超过背包最大承重的情况下,选择物品以最大化总重量,最后通过判断是否达到最大承重来确定答案是YES还是NO。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

Mary公司在三八妇女节准备了礼物,员工可以用礼物将自己的背包装满。由于物品较多,且每个物品都有自己的重量,而Mary的背包只能承受固定的重量,她很烦恼如何才能装满自己的包包,所以现在交给你来将Mary的背包装满吧。

注意:每种物品只能选一次,不考虑包的空间大小。

解答要求
时间限制:1000ms, 内存限制:64MB
输入
输入第一行包含两个空格分开的整数N(1≤ N ≤ 100)和S(1≤ S ≤ 1000),现场有N个物品和Mary的背包最多只能装S千克的物品;第二行是N个正整数Wi(0 < Wi ≤ 100),表示每个物品的重量(单位千克)。

输出
若能将Mary的背包装满则输出“YES”,否则输出“NO”。

样例1

输入样例
3 5
1 3 2
输出样例
YES

解题思路一

该题属于01背包问题,对一个物品只有拿或者不拿两种,设总重量为W,每样物品的重量为wi ,物品拿的数量为xi(0或1) , 则原题可抽象为
w1x1 + w2x2 + w3x3 + … + wixi = W
设当前背包的容量为j, 物品的重量为wi, 状态转移方程为
j < wi: xi = 0, F(i, j) = F(i-1, j)
j <= wi: F(i, j) = max(F(i-1, j), F(i-1, j-wi) + wi)
只需要判断决策全部完成后最后一个数是不是W即可

Python3 代码

N, W = map(int, input().split())
weights = [int(i) for i in input().split(' ')]

def func():
    if sum(weights) < W:
        print('NO')
    weights.insert(0, 0)
    dp = []
    for i in weights:
        dp.append([0] * (W + 1))
    for i, _ in enumerate(dp):
        if i == 0:
            continue
        for j in range(1, W + 1):
            weight = weights[i]
            if j < weight:
                dp[i][j] = dp[i-1][j]
            else:
                dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight] + weight)
    if dp[-1][-1] == W:
        print('YES')
    else:
        print('NO')

func()

解题思路二

用一维数组记录状态。初始值True,表示空背包装下空物品。然后遍历每个物品,再从后往前遍历背包容量,一直到容量<=物品重量。如果dp[j-w]为true,表示放下这个物品就能满;如果dp[j]为true,表示不拿也满了,两种情况都置为True

N, W = map(int, input().split())
weights = [int(i) for i in input().split(' ')]

def func():
    if sum(weights) < W:
        print('NO')
    dp = [False] * (W + 1)
    dp[0] = True
    for w in weights:
        for j in range(W, w - 1, -1):
            dp[j] = dp[j] or dp[j - w]
    if dp[W]:
        print('YES')
    else:
        print('NO')
func()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值