题目

https://lydsy.com/JudgeOnline/problem.php?id=1190

题解

好神仙的一道题啊。

既然 \(w_i = a_i\cdot 2^{b_i}\),那么不妨按照 \(b_i\) 来分组,每一组内部先做一个 01 背包,记为 \(f[i][j]\)。

然后考虑怎么求出最后的总答案。

下面就是很妙的部分了:

\(dp[i][j]\) 表示前 \(i\) 位中,容量 \(\leq j\cdot 2^i+(W\&(2^i-1))\) 的最大价值。

转移的时候我们枚举给 \(i-1\) 及以下的位多少容量,如果给了 \(k\),那么实际上下一位获得的就是 \(2k + W_{i-1}\),\(W_i\) 表示 \(W\) 的第 \(i-1\) 位。于是直接从 \(dp[i-1][2k+W_{i-1}]+f[i][j-k]\) 转移就可以了。

这个方法妙就妙在,发现我们不容易直接合并出 \(W\) 的限制,但是发现如果要合并出 \(W\),需要知道的是对于每一个 \(i\),某个在那一维上的容量 \(j\cdot 2^i\) 加上关于 \(W\) 在后面的位的情况,而这个东西可以进一步下去求。


#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 100 + 7;
const int M = 31 + 3; int n, w;
int siz[M], dp[M][N * 10];
pii v[M][N]; inline void work() {
memset(dp, 0, sizeof(dp));
for (int k = 0; k <= 31; ++k) {
int len = siz[k], mm = 10 * n;
for (int i = 1; i <= len; ++i)
for (int j = mm; j >= v[k][i].fi; --j)
smax(dp[k][j], dp[k][j - v[k][i].fi] + v[k][i].se);
if (k == 0) continue;
for (int i = mm; ~i; --i)
for (int j = 0; j <= i; ++j) smax(dp[k][i], dp[k][i - j] + dp[k - 1][std::min(mm, (j << 1) + ((w >> (k - 1)) & 1))]);
}
printf("%d\n", dp[31][0]);
} inline void init() {
memset(siz, 0, sizeof(siz));
for (int i = 1; i <= n; ++i) {
int c, a, b = 0;
read(a), read(c);
while (!(a & 1)) a >>= 1, ++b;
v[b][++siz[b]] = pii(a, c);
}
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
while (read(n), read(w), ~n && ~w) {
init();
work();
}
fclose(stdin), fclose(stdout);
return 0;
}

bzoj1190 [HNOI2007]梦幻岛宝珠 背包的更多相关文章

  1. BZOJ 1190 [HNOI2007]梦幻岛宝珠(背包)

    1190: [HNOI2007]梦幻岛宝珠 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1385  Solved: 798[Submit][Stat ...

  2. 【题解】 bzoj1190: [HNOI2007]梦幻岛宝珠 (动态规划)

    bzoj1190,懒得复制,戳我戳我 Solution: 这道题其实是一个背包(分组背包),但是由于数字比较大,就要重新构造dp式子.啃了三天才懂. \(dp[i][j]\)表示背包容积为\(j*2^ ...

  3. [HNOI2007]梦幻岛宝珠(背包)

    给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值.数据范围:N<=100;W<=2^30,并且保证每颗宝石的重量符 ...

  4. bzoj1190 [HNOI2007]梦幻岛宝珠

    传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1190 [题解] 首先,我们把所有物品都分解成$a\times 2^b$的形式,然后把物品按 ...

  5. bzoj1190 [HNOI2007]梦幻岛宝珠 动态规划

    给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值.数据范围:N<=100;W<=2^30,并且保证每颗宝石的重量符 ...

  6. 【BZOJ1190】[HNOI2007]梦幻岛宝珠 分层背包DP

    [BZOJ1190][HNOI2007]梦幻岛宝珠 Description 给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值. ...

  7. [BZOJ 1190][HNOI2007]梦幻岛宝珠

    1190: [HNOI2007]梦幻岛宝珠 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1057  Solved: 611[Submit][Stat ...

  8. luogu 3188 [HNOI2007]梦幻岛宝珠

    LINK:梦幻岛宝珠 时隔多日 我再次挑战这道题.还是以失败告终. 我觉得这一道背包真的有点难度 这是一个数量较少 但是价值和体积较大的背包. 通常的01背包 要不就是体积小 要么是价值小 但这道题给 ...

  9. BZOJ.1190.[HNOI2007]梦幻岛宝珠(分层背包DP)

    题目链接 把重量表示为\(a\times2^b\)的形式,然后按\(b\)排序. 从高到低枚举每一位,\(f[i]\)表示当前位容量为\(i\)时的最大价值(容量即\(a\times2^{bit}\) ...

随机推荐

  1. redis测试

    1,安装redis软件 2,引入redis jar包 3,案例 package test; import java.util.List; import redis.clients.jedis.Jedi ...

  2. 《数据结构与算法(C语言版)》严蔚敏 | 第五章 建立二叉树,并完成三/四种遍历算法

    PS:所有的代码示例使用的都是这个图 2019-10-29 利用p126的算法5.3建立二叉树,并完成三种遍历算法 中序 后序 先序 #include<iostream> #include ...

  3. [CSP-S模拟测试]:柱状图(树状数组+二分+三分)

    题目描述 $WTH$获得了一个柱状图,这个柱状图一共有$N$个柱子,最开始第$i$根柱子的高度为$x_i$,他现在要将这个柱状图排成一个屋顶的形状,屋顶的定义如下:$1.$屋顶存在一个最高的柱子,假设 ...

  4. xiugai完了

    <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Conten ...

  5. 洛谷P1441 砝码称重(搜索,dfs+dp)

    洛谷P1441 砝码称重 \(n\) 的范围为 \(n \le 20\) ,\(m\) 的范围为 \(m \le 4\) . 暴力遍历每一种砝码去除情况,共有 \(n^m\) 种情况. 对于剩余砝码求 ...

  6. MySQL定义数据库对象之指定definer

    mysql创建view.trigger.function.procedure.event时都会定义一个Definer: SQL SECURITY 有两个选项,一个为DEFINER,一个为INVOKER ...

  7. Skyline(6.x)-二次开发手册使用技巧

    毕业设计选择 Skyline 的 Web 端二次开发,由于以前没有接触过 ActiveX 控件的使用,二次开发手册是英文的读起来有点吃力,并且 IE 直接控制台输出 ActiveX 控件创建的对象看不 ...

  8. Oracle 数据库优化

    Oracle 数据库优化 参考网址

  9. HTTP 协议解析

    目录 目录 HTTP 协议 HTTP 协议工作原理 HTTP Request 请求行 Request Header HTTP Response 状态行 Response Header Body HTT ...

  10. input只输入数字和小数后两位

    html:<input  name="" type="tel" value="" placeholder="请输入金额&qu ...