【bzoj 1190】梦幻岛宝珠(DP)
这题是在01背包问题的基础上,扩充了重量,需要用时间换空间。
思路:
1.仔细看题,注意到重量wi为a*2^b(a<=10,b<=30),很容易想到要按 b 分开做背包的DP。接下来的重点就是怎么使DP从b-1继承到b。
2.再仔细看题,发现只有一次询问,那么就可以在这个W上做文章——依W的大小进行所有的DP。由于是按b的大小进行DP,所以把数都看成二进制位来继承和转移,每对一组 b 相同的数做完后,就略去这一二进制位。
实现:
1.“去位”:若W的二进制数上第 i 位为1,那么这时背包里已经放的物品的重量的第 i 位为0或1都无所谓,装得了;若W的二进制数上第 i 位为0,那么背包已有的重量的第 i 位为1就要从二进制的前一位借一个“1”拿来用。
2.对每组 b 进行DP时,直接用最大的背包容量N*wi(mW),之后转移时再按W进行修改就行了。
其中,以上实现可行的原因是:
对于每个第 i 位,它处于一个很“尴尬”的境地,它的前一位一给就是给“1”,对于它就是“2”了,多了也无需退回去。因为对于每个第 j 位,它的下一位根本就帮不了它,贡献“1”对于它也只是“0.5”,是没有用的。因此要略去某一位时,只需干脆地按W是否能满足它这一位的需求来对自己的前一位进行调整。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<algorithm>
6 using namespace std;
7
8 typedef long long LL;
9 const int N=110,M=30,mW=1000;
10 int n,W;
11 struct node{int w,v,a,b;}s[N];
12 LL f[M+10][mW+10];
13
14 bool cmp(node x,node y)
15 { return x.b<y.b; }
16 LL mmax(LL x,LL y)
17 { return x>y?x:y; }
18
19 int main()
20 {
21 while (1)
22 {
23 scanf("%d%d",&n,&W);
24 if (n==-1&&W==-1) break;
25 for (int i=1;i<=n;i++)
26 {
27 scanf("%d%d",&s[i].w,&s[i].v);
28 s[i].a=s[i].w,s[i].b=0;
29 while (s[i].a%2==0) s[i].a/=2,s[i].b++;
30 }
31 sort(s+1,s+1+n,cmp);
32 int l,r;
33 l=1;
34 memset(f,0,sizeof(f));
35 for (int i=0;i<=M;i++)
36 {
37 r=l-1;//
38 while (r<n && s[r+1].b==i) r++;//<n
39 for (int j=l;j<=r;j++)
40 for (int k=mW;k>=s[j].a;k--)
41 f[i][k]=mmax(f[i][k],f[i][k-s[j].a]+s[j].v);
42 for (int j=0;j<=mW;j++)//or (int j=mW;j>=0;j--)
43 if (W&(1<<i)) f[i+1][j>>1]=mmax(f[i+1][j>>1],f[i][j]);
44 else f[i+1][(j+1)>>1]=mmax(f[i+1][(j+1)>>1],f[i][j]);
45 l=r+1;
46 }
47 printf("%lld\n",f[31][0]);
48 }
49 return 0;
50 }
【bzoj 1190】梦幻岛宝珠(DP)的更多相关文章
- BZOJ 1190 梦幻岛宝珠(分组01背包)
跑了7000ms... 这是个体积和价值都超大的背包.但是体积保证为a*2^b的(a<=10,b<=30)形式.且n<=100. 于是可以想到按b来分组.这样的话每组最多为a*n*2 ...
- [BZOJ 1190][HNOI2007]梦幻岛宝珠
1190: [HNOI2007]梦幻岛宝珠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1057 Solved: 611[Submit][Stat ...
- BZOJ 1190 [HNOI2007]梦幻岛宝珠(背包)
1190: [HNOI2007]梦幻岛宝珠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1385 Solved: 798[Submit][Stat ...
- E - 梦幻岛宝珠 HYSBZ - 1190 变形01背包 难
E - 梦幻岛宝珠 HYSBZ - 1190 这个题目我觉得很难,看题解都看了很久. 首先可以得到一个大概的思路就是分组,每一个数都可以分成 a*2^b 所以把b相同的数都分成一个组. 在每一组内部 ...
- 【BZOJ1190】[HNOI2007]梦幻岛宝珠 分层背包DP
[BZOJ1190][HNOI2007]梦幻岛宝珠 Description 给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值. ...
- luogu 3188 [HNOI2007]梦幻岛宝珠
LINK:梦幻岛宝珠 时隔多日 我再次挑战这道题.还是以失败告终. 我觉得这一道背包真的有点难度 这是一个数量较少 但是价值和体积较大的背包. 通常的01背包 要不就是体积小 要么是价值小 但这道题给 ...
- BZOJ.1190.[HNOI2007]梦幻岛宝珠(分层背包DP)
题目链接 把重量表示为\(a\times2^b\)的形式,然后按\(b\)排序. 从高到低枚举每一位,\(f[i]\)表示当前位容量为\(i\)时的最大价值(容量即\(a\times2^{bit}\) ...
- 1190: [HNOI2007]梦幻岛宝珠 - BZOJ
Description 给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值. 数据范围:N<=100;W<=2^30 ...
- [HNOI2007]梦幻岛宝珠 「套路:分层 $DP$」
显然直接 \(01\) 背包会超时并且超空间 套路:分层 \(DP\) 「考虑将每个子结构看作一层(也就是包含了不止 \(1\) 个物品的信息),并且大层不会对小层造成影响,可以考虑先进行每一层的自我 ...
随机推荐
- C#处理医学图像(二):基于Hessian矩阵的医学图像增强与窗宽窗位
根据本系列教程文章上一篇说到,在完成C++和Opencv对Hessian矩阵滤波算法的实现和封装后, 再由C#调用C++ 的DLL,(参考:C#处理医学图像(一):基于Hessian矩阵的血管肺纹理骨 ...
- 深入剖析setState同步异步机制
关于 setState setState 的更新是同步还是异步,一直是人们津津乐道的话题.不过,实际上如果我们需要用到更新后的状态值,并不需要强依赖其同步/异步更新机制.在类组件中,我们可以通过thi ...
- 利用iptables防火墙保护web服务器
实例:利用iptables防火墙保护web服务器 防火墙--->路由器-->交换机-->pc机 配置之前,清空下已有的规则,放在规则冲突不生效 工作中,先放行端口写完规则,再DROP ...
- service代理模式及负载均衡
[root@k8s-master ~]# vim service.yaml apiVersion: v1 kind: Service metadata: name: my-service spec: ...
- Linux删除文件后磁盘目录不释放
今天测试oracle数据库的时候,把表空间连带内容和数据文件一并删除了,但是删除之后,查看数据文件不存在了,但是目录的带下没有释放 SQL> drop tablespace users incl ...
- oracle新增ID主键列,如何补全旧数据的ID值
1.创建SEQUENCE CREATE SEQUENCE MONKEY.TEST_ADD_IDCOL_ID CACHE 100; 2.新增表栏位 ALTER TABLE MONKEY.TEST_ADD ...
- C++ STL 栈和队列
栈和队列 头文件 #include<queue> // 队列 #include<stack> //栈 定义方式 //参数就是数据类型 stack<int> s; q ...
- nmap的理解与利用(初级)
在命令窗口下输入命令等待,可以用回车来查看进度 nmap进行探测之前要把域名通过dns服务器解析为ip地址,我们也可以使用指定的dns服务器进行解析. nmap --dns-servers 主机地址 ...
- 从零开始学spring源码之ioc预热:bean的拓展和beanProcessor注册
上篇聊完了bean的解析,说起来做的事情很简单,把xml文件里面配置的标签全部解析到spring容器里面,但是spring做的时候,花了那么大代价去做,后面看看到底值不值得呢. 接下来看看prepar ...
- libuv工作队列
目录 1.说明 2.API 2.1.uv_queue_work 2.2.uv_cancel 3.代码示例 1.说明 libuv 提供了一个线程池,可用于运行用户代码,libuv 中的工作队列中的任务会 ...