【洛谷】P3188 [HNOI2007]梦幻岛宝珠
题目描述
给你N颗宝石,每颗宝石都有重量和价值。要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为
,并输出最大的总价值。
数据范围:N<=100;W<=2^30,并且保证每颗宝石的重量符合a*2^b(a<=10;b<=30)
输入格式
输入文件中包含多组数据。
每组数据的格式如下:
第一行是两个正整数n和W,1≤n≤100,1≤W≤2^30,分别表示宝石的数目和最多能带走的宝石重量。
接下来的n行,每行有两个正整数weighti和valuei,1≤weighti≤2^30, 0≤valuei≤2^30,
分别表示第i颗宝石的重量和价值,且保证weighti能写成a*2^b(1≤a≤10,0≤b≤30)的形式。
同一行的两个正整数之间用空格隔开。
最后一组数据的后面有两个-1,表示文件的结束。这两个-1并不代表一组数据,
你不需对这组数据输出结果。并且输入文件中数据的组数不超过20。
输出格式
对于输入的每组数据,输出一个整数C,表示小P最多能带走的宝石的总价值。
每个结果整数C单独占一行,且保证C不会超过2^30。
输入样例
4 10
8 9
5 8
4 6
2 5
4 13
8 9
5 8
4 6
2 5
16 75594681
393216 5533
2 77
32768 467
29360128 407840
112 68
24576 372
768 60
33554432 466099
16384 318
33554432 466090
2048 111
24576 350
9216 216
12582912 174768
16384 295
1024 76
-1 -1
输出样例
14
19
1050650
分析
乍一看,怎么又是背包。
再一看,woc,范围怎么这么大。
有一看,好像可以根据2的几次幂来分层,最后合并。
仔细一想,还不是要很大的空间和复杂度,而且还不会写。
再一想,千年等一回
最后放弃去网上找题解,结果发现有一个贪心,从一位与下一位的合并时,只考虑这一位1000以内的情况。
用dp[i][j]表示背包的容量已经占用了j*2^i+(w&((1<< i)-1))时的最大价值
先对于每一个i进行背包的合并,然后再考虑把每一位合并。
合并时,dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[i-1][2*k+((w>>(i-1) )&1)])
其中(2*k+((w>>(i-1))&1))可以通过倒推得到,用j*2^i+(w&((1<< i)-1))减去k*2^i+(w&((1<< i)-1))即可
upd 20191014
突然想到一种对dp转移式子的感性理解,第i位的k到第i-1位后就是k*2,而((w>>(i-1) )&1)就代表w在第i-1位是否有1
所以dp转移式子还可以优化成
dp[i][j]=max(dp[i][j],dp[i][j-k]+max(dp[i-1][2*k+((w>>(i-1) )&1)],dp[i-1][2*k]))
顺便把另一种写法也写了。。。。。。
好像物品可以一个一个加进去,时间上会有很大的优化,然而并不会写。
代码(不要在意那个O2)
#pragma GCC optimize (2)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,cnt,i,j,k,w,val,f[][];
int main()
{
while(scanf("%d%d",&n,&m))
{
if(n==-&&m==-)return ;
memset(f,,sizeof f);
for(i=;i<=n;i++)
{
scanf("%d%d",&w,&val);
cnt=;while(w%==)w/=,cnt++;
for(j=;j>=w;j--)f[cnt][j]=max(f[cnt][j],f[cnt][j-w]+val);
}
int lim=;
for(i=m;i;i/=)lim++;lim--;
for(i=;i<=lim;i++)for(j=min(, m>>i);j>=;j--)for(k=;k<=j;k++)
f[i][j]=max(f[i][j],f[i][j-k]+f[i-][min(,(k*)|((m>>(i-))&))]);
printf("%d\n",f[lim][]);
}
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long f[][];
int n,m,st[][][];
int main()
{
while(scanf("%d%d",&n,&m))
{
if(n==-&&m==-)return ;
memset(f,,sizeof f);memset(st,,sizeof st);
for(int i=,a,b,cnt;i<=n;i++)
{
scanf("%d%d",&a,&b);cnt=;
while(a%==)a/=,cnt++;
st[cnt][++st[cnt][][]][]=a;st[cnt][st[cnt][][]][]=b;
}
int lim=;for(int i=m/;i;i/=)lim++;
for(int i=;i<=lim;i++)
{
if(i)for(int j=;j<=;j++)f[i][j]=f[i-][min(,(j<<)|((m>>(i-))&))];
for(int j=;j<=st[i][][];j++)for(int k=min(m>>i,);k>=st[i][j][];k--)
f[i][k]=max(f[i][k],f[i][k-st[i][j][]]+st[i][j][]);
}
printf("%lld\n",f[lim][]);
}
}
【洛谷】P3188 [HNOI2007]梦幻岛宝珠的更多相关文章
- P3188 [HNOI2007]梦幻岛宝珠
传送门 注意到 $a,b$ 不大 考虑对每一个 $a*2^b$ 的 $b$ 分别背包 设 $f[i][j]$ 表示只考虑 $b=i$ 的物品时,容量为 $j= \sum a$ 的最大价值 这个就是普通 ...
- [BZOJ 1190][HNOI2007]梦幻岛宝珠
1190: [HNOI2007]梦幻岛宝珠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1057 Solved: 611[Submit][Stat ...
- 【BZOJ1190】[HNOI2007]梦幻岛宝珠 分层背包DP
[BZOJ1190][HNOI2007]梦幻岛宝珠 Description 给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值. ...
- BZOJ 1190 [HNOI2007]梦幻岛宝珠(背包)
1190: [HNOI2007]梦幻岛宝珠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1385 Solved: 798[Submit][Stat ...
- luogu 3188 [HNOI2007]梦幻岛宝珠
LINK:梦幻岛宝珠 时隔多日 我再次挑战这道题.还是以失败告终. 我觉得这一道背包真的有点难度 这是一个数量较少 但是价值和体积较大的背包. 通常的01背包 要不就是体积小 要么是价值小 但这道题给 ...
- 【题解】 bzoj1190: [HNOI2007]梦幻岛宝珠 (动态规划)
bzoj1190,懒得复制,戳我戳我 Solution: 这道题其实是一个背包(分组背包),但是由于数字比较大,就要重新构造dp式子.啃了三天才懂. \(dp[i][j]\)表示背包容积为\(j*2^ ...
- 洛谷 P3190 [HNOI2007]神奇游乐园 解题报告
P3190 [HNOI2007]神奇游乐园 Description 给你一个 \(m * n\) 的矩阵,每个矩阵内有个权值\(V(i,j)\) (可能为负数),要求找一条回路,使得每个点最多经过一次 ...
- 1190: [HNOI2007]梦幻岛宝珠 - BZOJ
Description 给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值. 数据范围:N<=100;W<=2^30 ...
- [HNOI2007]梦幻岛宝珠(背包)
给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值.数据范围:N<=100;W<=2^30,并且保证每颗宝石的重量符 ...
随机推荐
- toString()和equals()方法详解
一:toString()方法 Object中toString方法 public String toString() { return getClass().getName() + "@&qu ...
- Android笔记(五十四) Android四大组件之一——ContentProvider(一)
ContentProvider提供数据 在Android中,他的每个应用都是相互独立的,各自运行在自己的Dalvik虚拟机中,但现实使用中常常需要在多个应用之间进行数据交换,例如发短信需要获取联系人中 ...
- CV2识别图片A,B,C,D
这个模型是经过简单训练,只能识别四个英文字母:ABCD,是我为了提取答案才训练的,因为科大,百度,以及腾讯的识别不是很准,所以自己训练自己使用,希望能够给你带来方便.下面是训练好的model,如多你感 ...
- Python标准库-datatime和time
Python标准库-datatime和time 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.标准库datatime 1>.datatime模块 #!/usr/bin/e ...
- ssh本机失败(ssh: connect to host localhost port 22: Connection refused)
ssh本机失败(ssh: connect to host localhost port 22: Connection refused) 一. 问题描述 之前一直在服务上使用宝塔面板, 今天突发奇想, ...
- SpringCloud学习心得—1.3—Eureka与REST API
SpringCloud学习心得—1.3—Eureka与REST API Eureka的REST API接口 API的基本访问 Eureka REST APIEureka 作为注册中心,其本质是存储 ...
- Spring -07 -AOP [面向切面编程] - 使用注解@+ AspectJ 方式实现环绕/前/后等通知 -超简洁 --静态代理/动态代理{JDK/cglib}
1.spring 不会自动去寻找注解,必须告诉 spring 哪些包下的类中可能有注解;使用注解来取代配置文件.1.1 引入xmlns:context ,指定扫描范围 <context:comp ...
- UVA1194 Machine Schedule[二分图最小点覆盖]
题意翻译 有两台机器 A,B 分别有 n,m 种模式. 现在有 k 个任务.对于每个任务 i ,给定两个整数$ a_i\(和\) b_i$,表示如果该任务在 A上执行,需要设置模式为 \(a_i\): ...
- top命令定位CPU高占用代码
步骤如下: 1.使用top命令定位异常进程.可以看见12836的CPU和内存占用率都非常高 2.使用top -H -p 进程号查看异常线程 3.使用printf "%x\n" 线程 ...
- Div+CSS总结
之前最早接触是在牛腩新闻发布系统中,当时看到这些自己是一头雾水,不过好在我们已经形成了这样的学习习惯,先实践在接触理论,这样再学习理论的时候就会想到当初我是怎样的迷茫,这样自己印象更深刻. DIV+C ...