E10 背包DP 多重背包 二进制优化
视频链接:https://www.bilibili.com/video/BV1MA41177cg/
#include <iostream> #include <algorithm> using namespace std; const int N=210; int n, m; int v[N], w[N], s[N]; int f[N][N]; int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d%d%d",&v[i],&w[i],&s[i]); //费用,价值,数量 for(int i=1; i<=n; i++) //阶段:物品 for(int j=0; j<=m; j++) //状态:体积 for(int k=0; k<=s[i]&&k*v[i]<=j; k++) //决策:个数 f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]); printf("%d\n",f[n][m]); }
#include <iostream> #include <algorithm> using namespace std; const int N=210; int n, m; int v[N], w[N], s[N]; int f[N]; int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d%d%d",&v[i],&w[i],&s[i]); //费用,价值,数量 for(int i=1; i<=n; i++) //阶段:物品 for(int j=m; j>=v[i]; j--) //状态:体积 for(int k=0; k<=s[i]&&k*v[i]<=j; k++) //决策:个数 f[j]=max(f[j],f[j-k*v[i]]+k*w[i]); printf("%d\n",f[m]); }
#include<iostream> using namespace std; const int N=2005; //2000<2^12 int n,m; int v1,w1,s; int v[N*12],w[N*12]; int f[N]; int main(){ cin>>n>>m; // 二进制拆分 int num=1; for(int i=1;i<=n;i++){ cin>>v1>>w1>>s; for(int j=1;j<=s;j<<=1){ v[num]=j*v1; w[num++]=j*w1; s-=j; } if(s) v[num]=s*v1, w[num++]=s*w1; } // 01背包 for(int i=1;i<num;i++) for(int j=m;j>=v[i];j--) f[j]=max(f[j],f[j-v[i]]+w[i]); cout<<f[m]; }
// 二进制分组优化 #include<iostream> using namespace std; const int N=100005; int n,m,a,b,s; int v[N],w[N]; int f[N]; int main(){ cin>>n>>m; int cnt=0; for(int i=1;i<=n;i++){ cin>>b>>a>>s; for(int j=1;j<=s;j<<=1){ v[++cnt]=j*a; w[cnt]=j*b; s-=j; } if(s) v[++cnt]=s*a, w[cnt]=s*b; } for(int i=1;i<=cnt;i++) for(int j=m;j>=v[i];j--) f[j]=max(f[j],f[j-v[i]]+w[i]); cout<<f[m]; }