//01背包 #include<cstdio> #include<iostream> #include<algorithm> using namespace std; int W[30001]; int C[2001]; int R[2001][30001]; int main(){ int N,M; cin>>N>>M; for(int i=1;i<=N;i++) cin>>C[i]>>W[i]; for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) if(j>=C[i]) { R[i][j]=max(R[i-1][j],R[i-1][j-C[i]]+W[i]); } else { R[i][j]=R[i-1][j]; } cout<<R[N][M]; return 0; } //完全背包 #include <iostream> #include <algorithm> using namespace std; const int maxn=300001; int f[maxn],w[maxn],c[maxn]; int main(){ ios::sync_with_stdio(false); int n,m; cin>>m>>n; for(int i=1;i<=n;i++) cin>>w[i]>>c[i]; for(int i=1;i<=n;i++) for(int j=w[i];j<=m;j++) f[j]=max(f[j],f[j-w[i]]+c[i]); cout<<f[m]; return 0; } //多重背包 #include <iostream> #include <algorithm> using namespace std; const int maxn=300001; int f[maxn],v[maxn],w[maxn],c[maxn]; int main(){ ios::sync_with_stdio(false); int n,m; cin>>n>>m; int x,y,z,k=0; for(int i=1;i<=n;i++){ cin>>x>>y>>z; int l=1; while(z>=l){ v[++k]=x*l; w[k]=y*l; z-=l;//每次减一是处理余数,计算余数大小 l*=2; } v[++k]=x*z; w[k]=y*z; //把 n[i]-2*k+1 分类 (处理余数) }//其实只用快速将物品分类为对数级,后面操作解决为覆盖到的情况 假设有1000个苹果,现在要取n个苹果,如何取?正常的做法应该是将苹果一个一个拿出来,直到n个苹果被取出来。 又假设有1000个苹果和10只箱子,如何快速的取出n个苹果呢?可以在每个箱子中放 2^i (i<=0<=n)个苹果,也就是 1、2、4、8、16、32、64、128、256、489(最后的余数),相当于把十进制的数用二进制来表示,取任意n个苹果时,只要推出几只箱子就可以了。 for(int i=1;i<=k;i++) //相当于转化为数量为k的01背包 for(int j=m;j>=v[i];j--) //正常的滚动数组操作,之后直接套了 。从小到大更新覆盖所有情况 f[j]=max(f[j],f[j-v[i]]+w[i]); cout<<f[m]; return 0; //没有多重背包题,代码只能存到A+B。。。。。。。。。。。 } //混合背包 g[i]=0为完全背包; g[i]不为0,那g[i]的值为能购买数量 #include <iostream> #include <algorithm> using namespace std; const int maxn=300001; int f[maxn],w[maxn],c[maxn],g[maxn]; int main(){ ios::sync_with_stdio(false); int n,m; cin>>m>>n; for(int i=1;i<=n;i++) cin>>w[i]>>c[i]>>g[i]; for(int i=1;i<=n;i++) if(g[i]==0){ for(int j=w[i];j<=m;j++) f[j]=max(f[j],f[j-w[i]]+c[i]); } else{ for(int k=1;k<=g[i];k++) for(int j=m;j>=w[i];j--) f[j]=max(f[j],f[j-w[i]]+c[i]); } cout<<f[m]; return 0; } //多维费用背包 { //#include <iostream> //#include <algorithm> // //using namespace std; // //const int maxn=2010,maxm=100; //int f[maxm][maxn][maxn],w[maxn],c[maxn]; // //int main(){ // // ios::sync_with_stdio(false); // // int n,v,m; // // cin>>n>>v>>m; // // for(int i=1;i<=n;i++) cin>>w[i]>>c[i]; // // for(int i=1;i<=n;i++) // // for(int j=v;j>=1;j--) // // for(int z=m;z>=1;z--) // // if(w[i]<=v and c[i]<=m) f[i][j][z]=max(f[i-1][j][z],f[i-1][j-w[i]][z-c[i]]+1); // // else f[i][j][z]=f[i-1][j][z]; // // cout<<f[n][v][m]; // // return 0; //} } #include <iostream> #include <algorithm> using namespace std; const int maxn=3000; int f[maxn][maxn],w[maxn],c[maxn]; int main(){ ios::sync_with_stdio(false); int n,v,m; cin>>n>>v>>m; for(int i=1;i<=n;i++) cin>>w[i]>>c[i]; for(int i=1;i<=n;i++) for(int j=v;j>=w[i];j--) //两次滚动数组操作,增加一维空间,多一层循环 for(int z=m;z>=c[i];z--) f[j][z]=max(f[j][z],f[j-w[i]][z-c[i]]+1); cout<<f[v][m]; return 0; } // 滚动数组来优化果断要ac 分组背包 10 6 3 2 1 1 3 3 1 4 8 2 6 9 2 2 8 3 3 9 3 for(int i=1;i<=n;i++) cin>>w[i]>>c[i]>>P; a[p][++a[p][0]]=i; a[1][a[1][0]=1]=1; a[1][a[1][0]=2]=2; a[2][a[2][0]=1]=3; a[2][a[2][0]=2]=4; a[3][a[3][0]=1]=5; a[3][a[3][0]=2]=6; //设a[k][0]为其中一组的个数; //设a[k][i]为其中一组中的成员序数; cin>>m>>n>>t;// n为个数,t为组数; for(int i=1;i<=n;i++){ cin>>w[i]>>c[i]>>p; a[p][++z]=i; //z=0; } for(int k=1;k<=t;k++) for(int j=m;j>=0;j--) for(int i=1;i<=a[k][0];i++) // for(int i=1;i<=a[k][0];i++) // // for(int j=m;j>=w[a[k][i]];j--) 如果这样写不保证每组只放一个,可能将多个放入; if(j>=w[a[k][i]]) f[j]=max(f[j],f[j-w[a[k][i]]+c[a[k][i]]); cout<<f[m]; return 0; //前面推倒完就上代码; #include <iostream> #include <algorithm> using namespace std; const int maxn=300001,maxm=3000; int f[maxn],w[maxn],c[maxn]; int a[maxm][maxm]; int main(){ ios::sync_with_stdio(false); int m,n,p,z=0; cin>>m>>n>>p; for(int i=1;i<=n;i++){ cin>>w[i]>>c[i]>>p; a[p][++a[p][0]]=i;//不用单一变量表示,是因为换组是时需重置,比较麻烦,所以用a[p][0]; } for(int k=1;k<=n;k++) for(int j=m;j>=0;j--) for(int i=1;i<=a[k][i];i++) if(j>=w[a[k][i]]) f[j]=max(f[j],f[j-w[a[k][i]]]+c[a[k][i]]); cout<<f[m]; return 0; } 背包的方案数 #include <cstdio> #include <algorithm> #include <iostream> using namespace std; const int maxn=300001; int f[maxn],a[maxn]; inline int read(){ int num=0,f=1; char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); } while(isdigit(c)){ num=num*10+c-'0'; c=getchar(); } return num*f; } int main(){ f[0]=1; int n,m; n=read(); m=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) for(int j=m;j>=a[i];j--) for(int k=1;k<=j/a[i];k++)//k层可以优化掉,这层并没有什么卵用 f[j]+=f[j-k*a[i]];//设f[j]为总额为 j的方案数,j-k*a[i]从上一总额推来 cout<<f[m]; return 0; } //3 10 //1 //2 //5 // //f[10]+=f[9]; //.... //f[10]+=f[0]; // full f[10]=1; // //f[9]+=f[8]; // i=1时,i的每次更新都重新更新新的f值 int main(){ for(int i=1;i<=n;i++) for(int j=a[i];j<=m;j++) f[j]+=f[j-a[i]];//或者设f[j]为面值为j的方案数,从上一面值推来 j-a[i]为上一面值 }