包子凑数/动态规划/背包问题总结(0-1背包,完全背包)

包子凑数/动态规划/背包问题总结(0-1背包,完全背包)_第1张图片

包子凑数/动态规划/背包问题总结(0-1背包,完全背包)_第2张图片 

题解: 

首先来系统回顾一下背包问题(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)

你可能感兴趣的:(蓝桥杯真题,动态规划,算法)