单调队列优化多重背包
2016-10-19 10:44
316 查看
多重背包的最原始的状态转移方程:
令 c[i] = min(num[i], j / v[i])
f[i][j] = max(f[i-1][j-k*v[i]] + k*w[i]) (1 <= k <= c[i]) 这里的 k 是指取第 i 种物品 k 件。
如果令 a = j / v[i] , b = j % v[i] 那么 j = a * v[i] + b.
这里用 k 表示的意义改变, k 表示取第 i 种物品的件数比 a 少几件。
那么 f[i][j] = max(f[i-1][b+k*v[i]] - k*w[i]) + a*w[i] (a-c[i] <= k <= a)
可以发现,f[i-1][b+k*v[i]] - k*w[i] 只与 k 有关,而这个 k 是一段连续的。我们要做的就是求出 f[i-1][b+k*v[i]] - k*w[i] 在 k 取可行区间内时的最大值。
k 取可行区间内时的最大值。k 取可行区间内时的最大值。k 取可行区间内时的最大值。
这句话特别重要,两个晚上理解了这句话。
m[i] = min(n[i], j / v[i])。
F[i][j]就是求这个队列最大长度为m[i] + 1时,队列中元素的最大值,加上a * w[i]。
这就可以使用单调队列优化。
f[i][j] = max(f[i-1][b+k*v[i]] - k*w[i]) + a*w[i] (a-c[i] <= k <= a)
例题
http://www.cnblogs.com/JoeFan/p/4168024.html
codevs
5429
令 c[i] = min(num[i], j / v[i])
f[i][j] = max(f[i-1][j-k*v[i]] + k*w[i]) (1 <= k <= c[i]) 这里的 k 是指取第 i 种物品 k 件。
如果令 a = j / v[i] , b = j % v[i] 那么 j = a * v[i] + b.
这里用 k 表示的意义改变, k 表示取第 i 种物品的件数比 a 少几件。
那么 f[i][j] = max(f[i-1][b+k*v[i]] - k*w[i]) + a*w[i] (a-c[i] <= k <= a)
可以发现,f[i-1][b+k*v[i]] - k*w[i] 只与 k 有关,而这个 k 是一段连续的。我们要做的就是求出 f[i-1][b+k*v[i]] - k*w[i] 在 k 取可行区间内时的最大值。
k 取可行区间内时的最大值。k 取可行区间内时的最大值。k 取可行区间内时的最大值。
这句话特别重要,两个晚上理解了这句话。
m[i] = min(n[i], j / v[i])。
F[i][j]就是求这个队列最大长度为m[i] + 1时,队列中元素的最大值,加上a * w[i]。
这就可以使用单调队列优化。
for (int i = 1; i <= n; ++i) { Ni = Num[i]; Vi = V[i]; Wi = W[i]; for (int j = 0; j < Vi; ++j) { Head1 = Tail1 = 0; Head2 = Tail2 = 0; Cnt = 0; for (int k = j; k <= m; k += Vi) { if (Tail1 - Head1 == Ni + 1) { if (Q2[Head2 + 1] == Q1[Head1 + 1]) ++Head2; ++Head1; } t = f[k] - Cnt * Wi; Q1[++Tail1] = t; while (Head2 < Tail2 && Q2[Tail2] < t) --Tail2; Q2[++Tail2] = t; f[k] = Q2[Head2 + 1] + Cnt * Wi;//可行性区间为cnt ++Cnt; } } }
f[i][j] = max(f[i-1][b+k*v[i]] - k*w[i]) + a*w[i] (a-c[i] <= k <= a)
例题
http://www.cnblogs.com/JoeFan/p/4168024.html
codevs
5429
#include<iostream> using namespace std; int f[10000],num[10000],v[10000],w[10000];int ps,qs,pe,qe; int q1[10000],q2[10000]; int main() { int n,m;cin>>n>>m; for (int i=1;i<=n;++i) { cin>>w[i]>>v[i]>>num[i]; } int ans=0; for (int i=1;i<=n;++i) { for (int j=0;j<w[i];++j) { ps=qs=1;//q为单调,q2单调 qe=pe=0; for (int k=j,cnt=0;k<=m;++cnt,k+=w[i]) { if (pe-ps==num[i]) { if (q1[ps]==q2[qs]) ++qs; ++ps; } int t=f[k]-cnt*v[i]; q1[++pe]=t; while (qs<=qe&&t>q2[qs]) --qe; q2[++qe]=t; f[k]=q2[qs]+cnt*v[i]; } } ans=max(ans,f[m]); } cout<<ans; }
相关文章推荐
- poj1742 Coins(多重背包+单调队列优化)
- poj 1742 多重背包 (单调队列优化)
- 背包模板(01,完全,多重背包的二进制优化和单调队列优化
- 多重背包中多次背包 O(VN) 算法1 (单调队列优化) 带参考程序
- POJ 1742 Coins 多重背包用单调队列优化
- [总结] 单调队列优化多重背包学习笔记
- 单调队列优化多重背包
- 多重背包单调队列优化
- 单调队列优化多重背包(pascal及翻译过去的C代码)
- 单调队列优化的多重背包
- poj 2754 Similarity of necklaces 2 转换成多重背包,单调队列优化/ 二进制优化
- 单调队列优化多重背包(含构造问题<POJ 1742 coin>)
- 多重背包中多次背包 O(VN) 算法1 (单调队列优化) 带参考程序
- 多重背包单调队列优化
- POJ 1742 Coins——不要套单调队列优化多重背包的模板
- 多重背包,二进制优化,单调队列优化
- 【C++心路历程36】单调队列优化多重背包
- HDOJ 2191 (多重背包/二进制分解/单调队列优化DP)
- POJ - 1742 Coins 多重背包+(二进制优化||单调队列优化)
- POJ 1742 Coins(多重背包 + 单调队列优化)