洛谷.1782.旅行商的背包(背包DP 单调队列)
2018-02-22 16:35
447 查看
题目链接(卡常背包)
朴素的多重背包是: f[i][j] = max{ f[i-1][j-k*v[i]]+kw[i] },复杂度 \(O(nV*\sum num_i)\)
可以发现求max时有很多值是被重复枚举过的
换一种方程表示形式,对于每个v[i],设j=Kv[i]+r, K=j/v[i], r=j%v[i],即按照%v[i]的余数分别进行dp
枚举k=0~K-1,那么 f[i][j] = max{ f[i-1][k*v[i]+r]-kw[i] } + Kw[i]
里面这一部分可以用单调队列维护。
复杂度大概就是 \(O(nV)\)。二三层枚举相当于把0~V都跑了一遍且只有一遍。
另外二进制拆分也可做,复杂度 \(O(nV*\sum log(num_i))\)。由于数据随机下 num_i可能比较小,\(\sum log(num_i)\)是期望 \(O(n)\) 的
这种方法常数更小,所以比单调队列还快
另一问最大数量只有5,直接 \(V^2\) 暴力。。
注意当前枚举的体积now与数量的限制: 当队首最优值的体积(用的数量 \(k_h\))+当前物品最大体积(个数上限\(num\))<当前枚举的体积(\(k\))时,要弹出队首
另外最后直接输出f[V]?我觉得不太对啊,大概那m个物品一定会产生正权值?
卡常是真恶心==
朴素的多重背包是: f[i][j] = max{ f[i-1][j-k*v[i]]+kw[i] },复杂度 \(O(nV*\sum num_i)\)
可以发现求max时有很多值是被重复枚举过的
换一种方程表示形式,对于每个v[i],设j=Kv[i]+r, K=j/v[i], r=j%v[i],即按照%v[i]的余数分别进行dp
枚举k=0~K-1,那么 f[i][j] = max{ f[i-1][k*v[i]+r]-kw[i] } + Kw[i]
里面这一部分可以用单调队列维护。
复杂度大概就是 \(O(nV)\)。二三层枚举相当于把0~V都跑了一遍且只有一遍。
另外二进制拆分也可做,复杂度 \(O(nV*\sum log(num_i))\)。由于数据随机下 num_i可能比较小,\(\sum log(num_i)\)是期望 \(O(n)\) 的
这种方法常数更小,所以比单调队列还快
另一问最大数量只有5,直接 \(V^2\) 暴力。。
注意当前枚举的体积now与数量的限制: 当队首最优值的体积(用的数量 \(k_h\))+当前物品最大体积(个数上限\(num\))<当前枚举的体积(\(k\))时,要弹出队首
另外最后直接输出f[V]?我觉得不太对啊,大概那m个物品一定会产生正权值?
卡常是真恶心==
#include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() const int N=1e4+5; int n,m,V,f ,q ,nm ; inline int read() { int now=0,f=1;register char c=gc(); for(;!isdigit(c);c=gc()) if(c=='-') f=-1; for(;isdigit(c);now=now*10+c-'0',c=gc()); return now*f; } int main() { n=read(),m=read(),V=read(); for(int v,w,num,now,tmp,i=1; i<=n; ++i) { v=read(),w=read(),num=read(); for(int j=0; j<v; ++j) for(int k=0,h=1,t=0; (now=k*v+j)<=V; ++k)//now:当前体积 { tmp=f[now]-k*w; while(h<=t && q[t]<tmp) --t; nm[++t]=k, q[t]=tmp; if(nm[h]+num<k) ++h;//每次仅会弹出一个元素 f[now]=q[h]+k*w; } } for(int a,b,c,i=1; i<=m; ++i) { a=read(),b=read(),c=read(); for(int j=V; j; --j) for(int k=0; k<=j; ++k) f[j]=std::max(f[j],f[j-k]+(a*k+b)*k+c); } // int res=f[1]; // for(int i=2; i<=V; ++i) res=std::max(res,f[i]); printf("%d",f[V]); return 0; }
相关文章推荐
- 洛谷P1776 宝物筛选_NOI导刊2010提高(02)(多重背包,单调队列)
- 【DP】【单调队列--多重背包】
- hdu2191(单调队列优化dp,多重背包)
- HDOJ 2191 (多重背包/二进制分解/单调队列优化DP)
- Dividing(多重背包、单调队列优化dp)
- 【洛谷】2034 选择数字 DP+单调队列
- 洛谷 P1782 旅行商的背包(二进制优化下的DP)
- [Usaco2011][bzoj2442][洛谷2527]修剪草坪解题报告(dp,贪心,单调队列)
- 单调队列优化DP,多重背包
- bzoj3831 洛谷3572 little bird 单调队列优化dp
- 洛谷p1725 露琪诺 单调队列优化的DP
- URAL 1427. SMS(DP+单调队列)
- CDOJ 我要长高 (单调队列优化DP)
- 【BZOJ1499】[NOI2005]瑰丽华尔兹 单调队列+DP
- hdu 3530 Subsequence(dp单调队列优化)
- poj 1821 Fence(dp单调队列优化)
- [poj1821] Fence DP单调队列优化
- bzoj2442: [Usaco2011 Open]修剪草坪(单调队列优化dp)
- BZOJ.1010.[HNOI2008]玩具装箱toy(DP 斜率优化/单调队列 决策单调性)
- hdu 3401 单调队列优化DP