动态规划01背包之求解最优解方案数

我们设kry[i][j]为dp[i][j]的方案数,那么最优方案总数就是kry[N][M],我们分析下怎么求kry[i][j],对于01背包来说:

经过max函数取最大值后,如果dp[i][j]==dp[i-1][j] 或者 dp[i][j]==dp[i-1][j-weight[i]]+value[i] ,那么kry[i][j] = kry[i-1][j] 或者 kry[i][j] = kry[i-1][j-weight[i]]。也就是说,对于dp[i][j]==dp[i-1][j] 时,表明第i件不放入时价值更大,那么到状态[i][j]的方案数就应该等于到状态[i-1][j]的方案数。同理,如果dp[i][j]==dp[i-1][j-weight[i]]+value[i],说明第i件放入时价值更大,此时到状态[i][j]的方案数就应该等于到状态[i-1][j-weight[i]]的方案数。

而若dp[i-1][j] ==dp[i-1][j-weight[i]]+value[i],],则说明即可以通过状态[i-1][j]在不加入第i件物品情况下到达状态[i][j],又可以通过状态[i-1][j-C[i]]在加入第i件物品的情况下到达状态[i][j],并且这两种情况都使得价值最大且这两种情况是互斥的,那么此时kry[i][j] = kry[i-1][j] + kry[i-1][j-weight[i]](你可以这样理解:两种到目前的状态[i][j]的方案都是最优解,那最优解的方案总数就是两个最优解的方案数相加)。

还有一点需要注意的,就是kry[][]必须全部初始化为1。因为无论dp[i][j]中i, j的值是多少,dp[i][j]总是存在的,既然存在,那就说明至少有一种方案,因此初始化为1。这里可能有些难以理解,没事,先记着,慢慢就会懂了。
 

n,V = map(int,input().split())
dp = [0 for j in range(V+1)] # 背包体积为j时能达到的最大价值
key = [1 for j in range(V+1)] # 背包体积为j时能达到最大价值的方案数
 
for i in range(1,n+1):
    v,w = map(int,input().split())
    for j in range(V,v-1,-1):
        # 和01背包很像 只不过转移到对象是方案数
        if dp[j] == dp[j-v]+w : key[j] += key[j-v]
        elif dp[j] < dp[j-v]+w : key[j] = key[j-v]
        dp[j] = max(dp[j], dp[j-v]+w)
print(key[V])

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值