我们设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])