LINK:梦幻岛宝珠

时隔多日 我再次挑战这道题。还是以失败告终。

我觉得这一道背包真的有点难度 这是一个数量较少 但是价值和体积较大的背包。

通常的01背包 要不就是体积小 要么是价值小 但这道题给了价值和体积都大 说明必然有其他重要的条件。

那就是体积为\(a*2^b\) \(a\leq 10,b\leq 30\)

只有这一个有利用价值的东西 我们无奈的对这个东西进行dp 对b进行分组 然后各个组进行dp.

关键我们如何把这些组给合起来。我想了很久 也翻了好几篇题解。

我终于明白为什么了。这个题 对我来说感觉很困难。

我们要得到容量为m的答案 还是考虑按位枚举背包的大小。

dp[i][j] 表示考虑到了第i为 此时我们背包的容量为\(j\cdot 2^i+m&((1<<i)-1)\)容量为这么多时的价值。

之所以是这个因为我们是从小到大来记录到底拿了多少 考虑到了第i位 对于第i位 我们可能当前没有这么多钱 但是之后高位可能有所以当前就需要存一下这个状态而后面的是我们应该有了这么多的钱用来买了。

所以这样dp一下 可以发现对于j的枚举 最多1000 也可以记一个总量来辅助转移。

这样转移可以保证的是 这是类似于背包的转移 且也不需要开过大的空间。

可以证明这是正确的。

//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define ld long double
#define pb push_back
#define get(x) x=read()
#define gtc(x) scanf("%s",a+1)
#define gt(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define F first
#define S second
#define mk make_pair
#define mod 1000000009
#define RE register
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;char ch=getc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
return x*f;
}
const int MAXN=1010,maxn=33;
int n,m,mx;
vector<int>w[maxn],v[maxn];
int f[maxn][MAXN],c[maxn];
int main()
{
freopen("1.in","r",stdin);
while(1)
{
get(n);get(m);mx=0;
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
memset(w,0,sizeof(w));
memset(v,0,sizeof(v));
if(n==-1&&m==-1)break;
rep(1,n,i)
{
int x,y;
get(x);get(y);
int cnt=0;
while(1)
{
if(x&1)break;
x=x>>1;++cnt;
}
w[cnt].pb(x);v[cnt].pb(y);
mx=max(mx,cnt);c[cnt]+=x;
}
rep(0,mx,i)
{
rep(0,(int)(w[i].size())-1,j)
{
for(int k=c[i];k>=w[i][j];--k)
f[i][k]=max(f[i][k],f[i][k-w[i][j]]+v[i][j]);
}
}
int len=0;
while(m>>len)++len;--len;
//cout<<len<<endl;
rep(1,len,i)
{
c[i]+=(c[i-1]+1)/2;
//cout<<c[i]<<endl;
for(int j=c[i];j>=0;--j)
for(int k=0;k<=j;++k)
f[i][j]=max(f[i][j],f[i][j-k]+f[i-1][min(c[i-1],(k<<1)+((m>>(i-1))&1))]);
}
put(f[len][1]);
}
return 0;
}

虽然写完了 但是这道题 还需要再细细揣摩其中dp合并的思想。

luogu 3188 [HNOI2007]梦幻岛宝珠的更多相关文章

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

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

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

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

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

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

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

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

  5. 1190: [HNOI2007]梦幻岛宝珠 - BZOJ

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

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

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

  7. [HNOI2007]梦幻岛宝珠

    题解: 一道比较好的题目 首先比较显然的就是我们要按照a*2^b的b的顺序来枚举 那么状态f[i][j]表示当前在b,用了a*2^b 刚开始没想到怎么不同层之间搞 看了题解发现非常简单 由于每一层到最 ...

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

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

  9. [HNOI2007]梦幻岛宝珠 「套路:分层 $DP$」

    显然直接 \(01\) 背包会超时并且超空间 套路:分层 \(DP\) 「考虑将每个子结构看作一层(也就是包含了不止 \(1\) 个物品的信息),并且大层不会对小层造成影响,可以考虑先进行每一层的自我 ...

随机推荐

  1. 常用API - Scanner、Random、ArrayList

    API 概述 API(Application Programming Interface),应用程序编程接口. Java API是一本程序员的 字典 ,是JDK中提供给我们使用的类的说明文档. 这些类 ...

  2. 【状压DP】SCOI2005-洛谷P1896-互不侵犯 (状压例题)

    [状压DP]SCOI2005-洛谷P1896-互不侵犯 (状压例题) 标签(空格分隔): 状压DP 好久没写博客了,真的爽(误) 题目: 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方 ...

  3. 数学计算 LibreOJ - 2573

    题目描述 小豆现在有一个数 x ,初始值为 1 . 小豆有 Q 次操作,操作有两种类型: 1 m: x=x×m ,输出 xmodM : 2 pos: x=x/ 第 pos 次操作所乘的数(保证第 po ...

  4. 【华为云技术分享】跟唐老师学习云网络 : Kubernetes网络实现

    当今K8s独霸天下之时,咱们站在更高的角度,好好的看看K8s网络是以什么理念构筑的.以及一个容器集群的好保姆,是如何分别照顾 南北流量和东西流量的. 一.简单介绍下Kubernetes 略..容器集群 ...

  5. day30 继承、派生与多态,类中方法和内置函数

    目录 一.多继承出现的问题(mixins机制) 二.派生与方法重用 三.多态 1 什么是多态 2 为什么要有多态 3 python中多态的鸭子类型 四.绑定方法与非绑定方法 1 绑定方法 1.1对象的 ...

  6. java规范总结

    1.所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较. 说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在 Intege ...

  7. JVM 专题十六:StringTable

    1. String的基本特性 String:字符串,使用一对""引起来表示. String声明为final的,不可被继承. String实现了Serializable接口:表示字符 ...

  8. SQLAlchemy02 /SQLAlchemy对数据的增删改查操作、属性常用数据类型详解

    SQLAlchemy02 /SQLAlchemy对数据的增删改查操作.属性常用数据类型详解 目录 SQLAlchemy02 /SQLAlchemy对数据的增删改查操作.属性常用数据类型详解 1.用se ...

  9. 数据可视化之DAX篇(二十三)ALLEXCEPT应用示例:更灵活的累计求和

    https://zhuanlan.zhihu.com/p/67441847 累计求和问题,之前已经介绍过(有了这几个公式,你也可以快速搞定累计求和),主要是基于比较简单的情形,针对所有的数据进行累计求 ...

  10. Worktile完成新一轮融资,将发力研发管理赛道

    Worktile 宣布完成B+轮融资.本轮融资由亿联凯泰基金领投,老股东斯道资本.宽带资本跟投.该轮融资将用于公司产品技术研发及市场拓展. 作为企业服务行业的佼佼者,Worktile 始终以打造世界级 ...