AcWing
11. 背包问题求方案数
在dp
方面,按一般的01背包问题
处理。维护一个cnt
数组,初始时,每种容量对应价值的方案cnt==1
(什么都不取的一种方案)。当dp
数组中某一容量的价值更新到更大值时,更新该容量的cnt
数组值,cnt[j] = cnt[j-v]
;当有一另外的一种f[j-v] + w
,使得f[j-v] + w == f[j]
,那么令cnt[j] += cnt[j-v]
,因为对应j-v
容量下的每一种方案,通过该次迭代的物品,都能转移到j
容量下。最后输出f[m]
.
这样做的合理性在于,f[m]
一定对应最大价值;所有能达到最大价值的方案,其容量也一定在m
以内,一定会被归纳到cnt[m]
以内。
#include <bits/stdc++.h>
using namespace std;
int n, m;
const int M = 1010, MOD = 1e9 + 7;
int v, w;
int f[M], cnt[M];
int main(){
cin >> n >> m;
for(int i = 0; i <= m; i++) cnt[i] = 1;
for(int i = 1; i <= n; i++){
cin >> v >> w;
for(int j = m; j >= v; j--){
if(f[j - v] + w > f[j]){
f[j] = f[j - v] + w;
cnt[j] = cnt[j - v];
}
else if(f[j - v] + w == f[j]) cnt[j] = (cnt[j] + cnt[j - v]) % MOD;
}
}
cout << cnt[m] << endl;
return 0;
}