01背包问题的情景:一个有固定重量的背包,容量为V。一共有n件商品,每件商品的价值为vi,让你挑选商品(每件物品只有一个),你挑选的商品重量不能超过背包的容量(小于等于),并且使得你挑选的物品价值最大(尽可能的使得价值最大)。
01背包问题的分析总的来说,其实就是状态方程的推导一般为f(i,j);
我们把背包看成是一个集合,01背包问题就是集合分成两部分,一个是不包含第i件商品,另一个是包含第i件商品;
方程分别就是f(i-1,j)和f(i-1,j-v[i])+w[i];
因此代码如下(二维):
#includeusing namespace std; int v[1005]; int w[1005]; int f[1005][1005]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { f[i][j]=f[i-1][j]; if(j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]); } cout< 但是二维我们最好可以优化成为一维数组
#includeusing namespace std; int v[1005]; int w[1005]; int f[1005]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) for(int j=m;j>=v[i];j--) { f[j]=max(f[j],f[j-v[i]]+w[i]); } cout< 2.完全背包 完全背包的情景和01背包的情景相似,但是商品是无限拿的,不是只有一件。
分析状态方程的时候,我们可以根据01方程的思想,想象一个集合,一部分是第i件物品没有拿,一个是第i件物品拿了,拿了多少件的我们定义为k件。
因此两部分的方程为f(i-1,j) f(i,j-k*v[i])+k*w[i])
所以代码如下(二维):
#includeusing namespace std; int v[1005]; int w[1005]; int f[1005][1005]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) for(int k=0;k*v[i]<=j;k++) { f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]); } cout< 这种情况一般都超时,因此要优化
#includeusing namespace std; int v[1005]; int w[1005]; int f[1005]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>v[i]>>w[i]; for(int i=1;i<=n;i++) for(int j=v[i];j<=m;j++) { f[j]=max(f[j],f[j-v[i]]+w[i]); } cout< 可以发现,其实01背包和完全背包就是二层循环不一样。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)