揹包九講(8)
阿新 • • 發佈:2022-04-21
揹包九講(8)
揹包問題求方案數
有 N 件物品和一個容量是 V的揹包。每件物品只能使用一次。
第 ii 件物品的體積是 vi,價值是 wi。
求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。
輸出 最優選法的方案數。注意答案可能很大,請輸出答案模 109+7 的結果。
輸入格式
第一行兩個整數,N,V,用空格隔開,分別表示物品數量和揹包容積。
接下來有 N 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i件物品的體積和價值。
輸出格式
輸出一個整數,表示 方案數 模 109+7 的結果。
資料範圍
0<N,V≤1000
0<vi,wi≤1000
輸入樣例
4 5 1 2 2 4 3 4 4 6
輸出樣例:
2
01揹包問題的變種,由於是記錄01揹包的方案數,所以在開一個數組g來記錄體積為N時的方案數。
#include<iostream> #include<algorithm> #include<vector> using namespace std; const int N = 1010; //01揹包環境下 int f[N];//記錄體積為N時最大價值 int g[N];//記錄體積為N時的方案數 int n,m; const int mod=1e9+7; const int INF=10000000; int main(){ cin>>n>>m; for(int i=1;i<=m;i++)f[i]=-INF;//f[N]初始化時,f[0]為0,其他全部初始化為負無窮,保證所有狀態從0開始計數 g[0]=1; for(int i=0;i<n;i++){ int v,w; cin>>v>>w; for(int j=m;j>=v;j--){ int t=max(f[j],f[j-v]+w); int s=0;//記錄體積為j時方案數 if(t==f[j])s+=g[j];//如果不拿的話,方案數應該是g[j]的方案數 if(t==(f[j-v]+w))s+=g[j-v];//如果拿的話,方案數應該是g[j-v]的方案數 if(s>=mod)s-=mod;//如果s大於mod,那麼減去取得就是模 f[j]=t;//更新f[j]和g[j] g[j]=s; } } int maxw=0; for(int i=0;i<=m;i++) maxw=max(maxw,f[i]);//選出最大價值 注意:我們並不是一定要用完所有體積,所以最大值應該在0-m去遍歷尋找 int res=0; for(int i=0;i<=m;i++){//再去遍歷一次,找到最大價值時,把最大價值時的方案數加上即可 if(f[i]==maxw){ res+=g[i]; if(res>=mod)res-=mod; } } cout<<res<<endl; return 0; }