[专题]有限背包计数问题

问题描述:有一个容量为n的背包和n个物品,第i个物品有cnt[i]个,每个物品的大小为i。求将背包刚好装满的方案数

定状态:f[i][j]表示使用前i个物品占用的大小为j的方案数

状态转移:对于状态f[i][j],可由以下状态转化而来:

  1. 就用前i-1个物品占用j大小,不使用当前的第i个物品,状态为f[i-1][j]
  2. 使用第i个物品,即用若干个1~i的物品组成j-i,再加上一个i物品,状态为f[i][j-i]。然而以上状态是不不全面的,因为f[i][j-i]状态已经使用了cnt[i]个i,那么没有再多的i供我们使用,即无法转移到f[i][j],因此我们减去在f[i][j-i]状态已经使用了cnt[i]个i的情况,最终得到状态为f[i][j-i]-f[i-1][j-i-i*i]

最终,f[i][j]=f[i-1][j]+f[i][j-i]-f[i-1][j-i-i*i],注意赋初值之后很容易写出来正解

思考:将原题目第i个物品有cnt[i]个改为有i个,其余条件不变。而n<=1e5。显然无法用上述方法解决,因此考虑优化

  • 对于第i个物品,如果i*i>n,我们可以将第i个物品看做无限个,因为无论如何i号物品也不可能用完
  • 因此我们想到了分类dp,对于前面sqrt(n)个数我们仍用上述方法做,而对于下面的数我们用g[i][j]表示在后半区间内选了i个物品凑成j的方案数
  • 有两种方案,第一种是将所有i个物品大小都加1,相当于改变了取的物品,这时总体的体积加了i,第二种方案是增加一个sqrt(n)+1大小的物品,这个物品在以后的讨论中会如同第一种方案一样一直增加……所以这两种方案其实是包含了所有情况的
  • 即:g[i][j]=g[i][j-i]+g[i-1][j-sqrt(n)-1]

最后将两个区间的解合并,枚举第一个区间的和,再枚举一下 后面那个区间 选几个数,再乘法原理算一下即可。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值