有 \(N\) 件物品和一个容量为 \(M\) 的背包。第 \(i\) 件物品所耗费的空间是 \(w[i]\),得到的价值是 \(v[i]\)。求解将哪些物品装入背包可使价值总和最大。
不过,省去了这一维,就出现了一个细节需要注意:要倒叙枚举 \(j\),而不是正序枚举,因为正序枚举在枚举 \(f[j]\) 时 \(f[j-w[i]]\) 已经被覆盖过了,那么就有可能取过了第 \(i\) 件物品,不满足动态规划的特性:无后效性。(自己手动推一下,会更理解)
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d %d",&w[i],&v[i]);
for (int i=1;i<=n;i++)
for (int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
有 \(N\) 件物品和一个容量为 \(M\) 的背包,每件物品都有无限件。放入 第 \(i\)件物品耗费的空间是 \(w[i]\),得到的价值是 \(v[i]\)。求解将哪些物品放入背包可使价值总和最大;
因为完全背包可以取无限次,枚举 \(f[j]\) 前第 \(i\) 件物品能够已经取过,符合完全背包
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d %d",&w[i],&v[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]]+v[i]);
有 \(N\) 种物品和一个容量为 \(M\) 的背包。第i种物品最多有 \(n[i]\) 件可用,每件费用是 \(w[i]\),价值是 \(v[i]\)。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
可是这种方法会超时 \(QAQ\),所以我们要用二进制优化
for (int i=1;i<=n;i++)
for (int j=1;n[i]>0;n[i]-=j,j=min(j*2,n[i]))
for (int k=v;k>=w[i]*j;k--)
f[k]=max(f[k],f[k-w[i]*j]+v[i]*j);
对于每件物品,具有两种不同的费用;选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。设这两种代价分别为代价\(1\)和代价\(2\),第\(i\)件物品所需的两种代价分别为 \(a[i]\) 和 \(b[i]\)。两种代价可付出的最大值(两种背包容量)分别为\(V\)和\(U\)。物品的价值为\(v[i]\)。
同样,可以压缩空间:\(f[v][u]=max(f[[j][k],f[j-a[i]][k-b[i]]+v[i])\)
for (int i=1;i<=n;i++)
for (int j=V;j>=a[i];j--)
for (int k=U;k>=b[i];k--)
f[j][k]=max(f[j][k],f[j-a[i]][k-b[i]]+v[i]);
有 \(N\) 件物品和一个容量为 \(V\) 的背包。第i件物品的费用是 \(w[i]\),价值是\(v[i]\)。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
其实对于这种题目,我们只是多一重循环枚举组中的物品,这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。具体看代码;
cpp for 所有的组k for (int j=V;j>=0;j--) for 所有的i属于组k f[j]=max{f[j],f[j-c[i]]+w[i]}
------------恢复内容开始------------
有 \(N\) 件物品和一个容量为 \(M\) 的背包。第 \(i\) 件物品所耗费的空间是 \(w[i]\),得到的价值是 \(v[i]\)。求解将哪些物品装入背包可使价值总和最大。
不过,省去了这一维,就出现了一个细节需要注意:要倒叙枚举 \(j\),而不是正序枚举,因为正序枚举在枚举 \(f[j]\) 时 \(f[j-w[i]]\) 已经被覆盖过了,那么就有可能取过了第 \(i\) 件物品,不满足动态规划的特性:无后效性。(自己手动推一下,会更理解)
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d %d",&w[i],&v[i]);
for (int i=1;i<=n;i++)
for (int j=m;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+v[i]);
有 \(N\) 件物品和一个容量为 \(M\) 的背包,每件物品都有无限件。放入 第 \(i\)件物品耗费的空间是 \(w[i]\),得到的价值是 \(v[i]\)。求解将哪些物品放入背包可使价值总和最大;
因为完全背包可以取无限次,枚举 \(f[j]\) 前第 \(i\) 件物品能够已经取过,符合完全背包
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d %d",&w[i],&v[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]]+v[i]);
有 \(N\) 种物品和一个容量为 \(M\) 的背包。第i种物品最多有 \(n[i]\) 件可用,每件费用是 \(w[i]\),价值是 \(v[i]\)。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
可是这种方法会超时 \(QAQ\),所以我们要用二进制优化
for (int i=1;i<=n;i++)
for (int j=1;n[i]>0;n[i]-=j,j=min(j*2,n[i]))
for (int k=v;k>=w[i]*j;k--)
f[k]=max(f[k],f[k-w[i]*j]+v[i]*j);
对于每件物品,具有两种不同的费用;选择这件物品必须同时付出这两种代价;对于每种代价都有一个可付出的最大值(背包容量)。问怎样选择物品可以得到最大的价值。设这两种代价分别为代价\(1\)和代价\(2\),第\(i\)件物品所需的两种代价分别为 \(a[i]\) 和 \(b[i]\)。两种代价可付出的最大值(两种背包容量)分别为\(V\)和\(U\)。物品的价值为\(v[i]\)。
同样,可以压缩空间:\(f[v][u]=max(f[[j][k],f[j-a[i]][k-b[i]]+v[i])\)
for (int i=1;i<=n;i++)
for (int j=V;j>=a[i];j--)
for (int k=U;k>=b[i];k--)
f[j][k]=max(f[j][k],f[j-a[i]][k-b[i]]+v[i]);
有 \(N\) 件物品和一个容量为 \(V\) 的背包。第i件物品的费用是 \(w[i]\),价值是\(v[i]\)。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
其实对于这种题目,我们只是多一重循环枚举组中的物品,这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。具体看代码;
for 所有的组k
for (int j=V;j>=0;j--)
for 所有的i属于组k
f[j]=max{f[j],f[j-c[i]]+w[i]}
原文:https://www.cnblogs.com/Michael-zx/p/12334836.html