E19 背包DP 求方案数
// 不超背包容量的方案数 O(n*m) #include<bits/stdc++.h> using namespace std; const int N=1010,M=1e9+7; int n,m,v,w; int f[N]; //f[j]表示背包容量为j时的最大价值 int g[N]; //g[j]表示背包容量为j时的方案数 int main(){ scanf("%d%d",&n,&m); for(int i=0;i<=m;i++) g[i]=1; //每个容量的方案初值均为1 for(int i=1;i<=n;i++){ scanf("%d%d",&v,&w); for(int j=m;j>=v;j--){ if(f[j-v]+w>f[j]){ //装物品i价值更大, f[j]=f[j-v]+w; //更新价值, g[j]=g[j-v]; //继承方案数 } else if(f[j-v]+w==f[j]){ //装物品i价值相等, g[j]=(g[j]+g[j-v])%M; //更新方案数 } } } printf("%d\n",g[m]); }
// 恰好装满的方案数 O(n*m) #include<bits/stdc++.h> using namespace std; const int N=1010,M=1e9+7; int n,m,v,w; int f[N]; //f[j]表示背包容量为j时的最大价值 int g[N]; //g[j]表示背包容量为j时的方案数 int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) f[i]=-10000; f[0]=0,g[0]=1; //初值不同 for(int i=1;i<=n;i++){ scanf("%d%d",&v,&w); for(int j=m;j>=v;j--){ if(f[j-v]+w>f[j]){ f[j]=f[j-v]+w; g[j]=g[j-v]; } else if(f[j-v]+w==f[j]){ g[j]=(g[j]+g[j-v])%M; } } } printf("%d\n",g[m]); }
//多人背包 求 01 背包前 K 优解的价值和 O(nVK) #include<bits/stdc++.h> using namespace std; int K,V,n,ans; int v[205],w[205]; int f[5005][55]; //f[j][k]表示背包容积 j 恰好装满,第 k 大的价值 int t[55]; int main(){ cin>>K>>V>>n; //50,5000,200 for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; memset(f,-0x3f,sizeof(f)); //恰好装满的初值 f[0][1]=0; for(int i=1; i<=n; i++){ for(int j=V; j>=v[i]; j--){ int c1=1,c2=1,cnt=0; while(cnt<=K){ //轮流记录体积为j的前K大价值 if(f[j][c1]>f[j-v[i]][c2]+w[i]) t[++cnt]=f[j][c1++]; else t[++cnt]=f[j-v[i]][c2++]+w[i]; } for(int k=1; k<=K; k++) f[j][k]=t[k]; } } for(int i=1;i<=K;i++) ans+=f[V][i]; cout<<ans; }
背包九讲——背包问题求方案数_1.给定n种物品和一个背包。物品i的重量是w[i],其价值为v[i],背包的容量为c。应如-CSDN博客
浙公网安备 33010602011771号