题解:
首先来系统回顾一下背包问题(0-1背包和完全背包最大不同就是遍历顺序)
0-1背包
1.物品只能拿一次
2.遍历顺序只能倒序
3.先遍历物品,再遍历背包
题型:
1.能够否装满容量为target的背包:return dp[target]==target
for i in range(len(weight)): for j in range(bagweight,weight[i]-1,-1): dp[j]=max(dp[j],dp[j-weight[i]]+value[i])
2.在一个容量为j的背包,最多能装多少?dp[j]
for i in range(len(weight)): for j in range(bagweight,weight[i]-1,-1): dp[j]=max(dp[j],dp[j-weight[i]]+value[i])
3.装满容量为j的背包,最多装多少次?dp[j]这种题型最为特殊,初始化dp[0]=1
for i in range(len(nums)): for j in range(bagweight,nums[i]-1,-1): dp[j]+=dp[j-nums[i]]
4.装满容量为j的背包,用到的物品数量最小为多少?dp[j],初始化dp[j]=math.inf
for i in range(len(nums)): for j in range(bagweight,nums[i]-1,-1): dp[j]=min(dp[j],dp[j-nums[i]]+1)
完全背包:
1.物品能拿无数次
2.遍历顺序为正序
3.涉及到求组合数时,先遍历物品再遍历背包(拿物品的顺序不能交换时)涉及到求排列数时,先遍历背包再遍历物品(那物品的顺序可以交换)
题型:
1.能够否装满容量为target的背包:return dp[target]==target
for i in range(len(weight)): for j in range(weight[i],bagweight+1): dp[j]=max(dp[j],dp[j-weight[i]]+value[i])
2.在一个容量为j的背包,最多能装多少?dp[j]
for i in range(len(weight)): for j in range(weight[i],bagweight+1): dp[j]=max(dp[j],dp[j-weight[i]]+value[i])
3.装满容量为j的背包,最多装多少次?dp[j]这种题型最为特殊,初始化dp[0]=1
for i in range(len(nums)): for j in range(nums[i],bagweight+1): dp[j]+=dp[j-nums[i]]
4.装满容量为j的背包,用到的物品数量最小为多少?dp[j],初始化dp[j]=math.inf,这里以先背包后物品举例
for j in range(bagweight+1): for i in range(len(nums)): if j>=nums[i]: dp[j]=min(dp[j],dp[j-nums[i]]+1)
本题即是完全背包中的“能否将背包装满”的问题
什么情况下会有无数个数无法凑出呢?
样例二的输入 3 2 4 6 其实已经给出了答案,如果所有的 ai 不互质,也就是说它们都是某一个大于1的数的倍数,就会有无数个的数无法凑出,毕竟这样的 ai 所能构造出的数都是它们 gcd 的倍数
import os
import sys
import math
# 请在此输入您的代码
n=int(input())
nums=[int(input()) for i in range(n)]
nums.sort()
g=math.gcd(nums[0],nums[1])
for i in range(2,n):
g=math.gcd(nums[i],g)
if g!=1:
print("INF")
else:
bagweight=9999
dp=[0]*(bagweight+1)
for i in range(n):
for j in range(nums[i],bagweight+1):
dp[j]=max(dp[j],dp[j-nums[i]]+nums[i])
ans=0
for i in range(bagweight+1):
if dp[i]!=i:
ans+=1
print(ans)