BZOJ 1190 [HNOI2007]梦幻岛宝珠
2016-11-09 21:30
344 查看
分组背包DP
看到w很大,不能直接做。但是w=a*2^b,且a,b都不大,就是让我们用2^a分组。
分组之后先组内DP求出f[i][j]表示仅在2^i组内,
容量为2^i*j时的最大价值。
然后组间DP再求出一个f[i][j]表示2^0~2^i组内,
容量为 j*2^i+(w&((1<< i)-1)) 时的最大价值
方程:cmax(f[i][j], f[i][k] + f[i-1][((j-k)<<1)+((W>>(i-1))&1)])
注意DP的时候第二维要从大到小- -
看到w很大,不能直接做。但是w=a*2^b,且a,b都不大,就是让我们用2^a分组。
分组之后先组内DP求出f[i][j]表示仅在2^i组内,
容量为2^i*j时的最大价值。
然后组间DP再求出一个f[i][j]表示2^0~2^i组内,
容量为 j*2^i+(w&((1<< i)-1)) 时的最大价值
方程:cmax(f[i][j], f[i][k] + f[i-1][((j-k)<<1)+((W>>(i-1))&1)])
注意DP的时候第二维要从大到小- -
#include<cstdio> #include<cstring> #include<algorithm> #define B 32 #define V 1005 #define cmax(u,v) (u)<(v)?(u)=(v):0 using namespace std; namespace ziqian { int f[B][V]; void main() { int n, W, ans; while(scanf("%d%d",&n,&W), n!=-1) { memset(f,0,sizeof(f)); ans = 0; for(int i = 1, v, a, b; i <= n; i++) { scanf("%d%d",&b,&v); a=0; while((b&1)==0) { a++; b>>=1; } for(int j = min(1000, W>>a); j >= b; j--) { cmax(f[a][j], f[a][j-b] + v); cmax(ans, f[a][j]); } } for(int i = 1; i < B && (1<<i) < W; i++) { for(int j = min(1000, W>>i); j >= 0; j--) { for(int k = j; k >= 0; k--) { cmax(f[i][j], f[i][k] + f[i-1][min( ((j-k)<<1)+((W>>(i-1))&1), 1000)]); } cmax(ans, f[i][j]); } } printf("%d\n",ans); } } } int main() { ziqian::main(); }
相关文章推荐
- [数位DP] BZOJ1190. [HNOI2007]梦幻岛宝珠
- BZOJ 1190 HNOI2007 梦幻岛宝珠 动态规划
- BZOJ 1190: [HNOI2007]梦幻岛宝珠
- 【BZOJ1190】[HNOI2007]梦幻岛宝珠 分层背包DP
- bzoj1190 [HNOI2007]梦幻岛宝珠 ( 二进制分组优化背包DP)
- [BZOJ 1190][HNOI2007]梦幻岛宝珠
- 【bzoj1190】[HNOI2007]梦幻岛宝珠 分层背包dp
- BZOJ 1190: [HNOI2007]梦幻岛宝珠 背包DP
- [bzoj1190][HNOI2007]梦幻岛宝珠 分组背包
- 1190: [HNOI2007]梦幻岛宝珠 - BZOJ
- [DP]BZOJ 1190——[HNOI2007]梦幻岛宝珠 动态规划]
- 1190: [HNOI2007]梦幻岛宝珠
- 分层背包 [HNOI2007]梦幻岛宝珠
- 【bzoj1190】[HNOI2007]梦幻岛宝珠 分层背包dp
- [DP 背包] BZOJ 1190 [HNOI2007]梦幻岛宝珠
- bzoj1190 梦幻岛宝珠 动态规划
- BZOJ 1190: [HNOI2007]梦幻岛宝珠
- 题解 P3188 【[HNOI2007]梦幻岛宝珠】 DP
- BZOJ 1190 梦幻岛宝珠 [01背包][二进制优化]
- BZOJ 1190 梦幻岛宝珠