题目描述
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()