(壹)01背包
有N个物品和一个体积为V的背包,每个物品体积为v[i],价值为w[i],问背包可收纳的最大价值。
时间复杂度O(N*V)。
/* f[m]即为答案。 如果要表示恰好去体积为V的物品, 可以把除f[0]外全置为负无穷, 以保证是f[m]从f[0]推来的。 */ #include<iostream> using namespace std; int N,V; int v[1010],w[1010],f[1010]; int main() { cin>>N>>V; for(int i=0;i<N;i++) cin>>v[i]>>w[i]; for(int i=0;i<N;i++) for(int j=V;j>=v[i];j--) f[j]=max(f[j],f[j-v[i]]+w[i]); cout<<f[V]<<endl; return 0; }
(贰)完全背包
有N种物品和一个体积为V的背包,每种物品体积为v[i],价值为w[i],且每种物品有无限个,问背包可收纳的最大价值。
时间复杂度O(N*V)。
/* f[m]即为答案。 如果要表示恰好去体积为V的物品, 可以把除f[0]外全置为负无穷, 以保证是f[m]从f[0]推来的。 */ #include<iostream> using namespace std; int N,V; int v,w,f[1010]; int main() { cin>>N>>V; for(int i=0;i<N;i++) { cin>>v>>w; for(int j=v;j<=V;j++) f[j]=max(f[j],f[j-v]+w); } cout<<f[V]<<endl; return 0; }
(叁)多重背包
有N种物品和一个V体积背包,每种物品体积为v[i],价值为w[i],个数为s[i],问背包可收纳的最大价值。
- 基本解法,时间复杂度O(N*∑si)。
#include<iostream> using namespace std; int N,V; int v,w,s,f[1010]; int main() { cin>>N>>V; for(int i=0;i<N;i++) { cin>>v>>w>>s; for(int j=V;j>=v;j--) for(int k=1; k<=s && k*v<=j ;k++) f[j]=max(f[j],f[j-k*v]+k*w); } cout<<f[V]<<endl; return 0; }
- 二进制优化,时间复杂度O(N*∑ log s[i])。
#include<iostream> using namespace std; int N,V; int f[2020]; int v[11010],w[11010]; int cnt=0; //2的11次方大于2000,故开11倍 int main() { int x,y,z; cin>>N>>V; for(int i=0;i<N;i++) { cin>>x>>y>>z; for(int j=1;j<=z;j<<=1) { v[cnt]=j*x; w[cnt++]=j*y; z-=j; } if(y) { v[cnt]=z*x; w[cnt++]=z*y; } } for(int i=0;i<cnt;i++) for(int j=V;j>=v[i];j--) f[j]=max(f[j],f[j-v[i]]+w[i]); cout<<f[V]<<endl; return 0; }
- 优先队列优化,时间复杂度O(NV)。