Description

“寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听。”
失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的感觉,却不能回忆起她的音容笑貌。 记忆中,她总是喜欢给Eden出谜题:在 valentine’s day 的夜晚,两人在闹市中闲逛时,望着礼品店里精巧玲珑的各式玩偶,她突发奇想,问了 Eden这样的一个问题:有n个玩偶,每个玩偶有对应的价值、价钱,每个玩偶都可以被买有限次,在携带的价钱m固定的情况下,如何选择买哪些玩偶以及每个玩偶买多少个,才能使得选择的玩偶总价钱不超过m,且价值和最大。众所周知的,这是一个很经典的多重背包问题,Eden很快解决了,不过她似乎因为自己的问题被飞快解决感到了一丝不高兴,于是她希望把问题加难:多次 询问,每次询问都将给出新的总价钱,并且会去掉某个玩偶(即这个玩偶不能被选择),再问此时的多重背包的答案(即前一段所叙述的问题)。  
这下Eden 犯难了,不过Eden不希望自己被难住,你能帮帮他么?

Input

第一行一个数n,表示有n个玩偶,玩偶从0开始编号 
第二行开始后面的 n行,每行三个数 ai, bi, c i,分别表示买一个第i个玩偶需
要的价钱,获得的价值以及第i个玩偶的限购次数。 
接下来的一行为q,表示询问次数。 
接下来q行,每行两个数di. ei表示每个询问去掉的是哪个玩偶(注意玩偶从0开始编号)以及该询问对应的新的总价钱数。(去掉操作不保留,即不同询问互相独立)

Output

输出q行,第i行输出对于第 i个询问的答案。

Sample Input

5
2 3 4
1 2 1
4 1 2
2 1 1
3 2 3
5
1 10
2 7
3 4
4 8
0 5

Sample Output

13
11
6
12
4

HINT

一共五种玩偶,分别的价钱价值和限购次数为 (2,3,4), (1,2,1), (4,1,2), (2,1,1),(3,2,3)。五个询问,以第一个询问为例。第一个询问表示的是去掉编号为1的玩偶,且拥有的钱数为10时可以获得的最大价值,则此时剩余玩偶为(2,3,4),(4,1,2),(2,1,1),(3,2,3),若把编号为0的玩偶买4个(即全买了),然后编号为3的玩偶买一个,则刚好把10元全部花完,且总价值为13。可以证明没有更优的方案了。注意买某种玩偶不一定要买光。 数据满足1 ≤ n ≤ 1000, 1 ≤ q ≤ 3*10的5次方 , 1 ≤  ai、bi、c i ≤ 100, 0 ≤ d i < n,  0  ≤ei ≤ 1000。 

x-1,x+1——n中取最优解,我们把它分成两半,分配左边一定数目的钱,分配右边一定数目的钱,由于之前做过完全背包,我们可以直接得出左边和右边在一定钱数下的最优解,

相加后即为一种可能的答案,当然我们需要枚举分配的钱数在不同的可能性之间进行比较才能达到最终答案。

我采用了二进制优化来避免超限。

ps:这个程序时间复杂度在最后有可能达到O(3*10^8),但是数据水,所以过去了,还是建议看那些大神的题解。

具体看程序:

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,t,x,y,z,maxm,now,ans,q,d[],e[],w[],v[],l[],r[],f[][],f2[][];
int max(int a,int b)
{
return (a>b?a:b);
}
int main()
{
scanf("%d",&n);
now=;
for (int i=;i<=n;i++)
{
t=;
l[i]=now;//记录这种物品被分开后在背包中开始的位置
scanf("%d %d %d",&x,&y,&z);
while ((t*-)<z)//转换为01背包,并且进行二进制优化
{
w[now]=t*x;
v[now]=t*y;
t*=;
now+=;
}
w[now]=(z-t+)*x;
v[now]=(z-t+)*y;
r[i]=now;//记录这种物品被分开后在背包中最后的位置
now+=;
}
scanf("%d",&q);
for (int i=;i<=q;i++)
{
scanf("%d %d",&d[i],&e[i]);
d[i]+=;
if (e[i]>maxm) maxm=e[i];//所有钱数中的最大值
}
for (int i=;i<=now;i++)//正着做01背包
for (int j=maxm;j>=;j--)
if (j-w[i]>=) f[i][j]=max(f[i-][j],f[i-][j-w[i]]+v[i]);
else f[i][j]=f[i-][j];
for (int i=;i<=now/;i++)//把背包倒过来
{
t=w[i]; w[i]=w[now-i+];w[now-i+]=t;
t=v[i]; v[i]=v[now-i+];v[now-i+]=t;
}
for (int i=;i<=now;i++)//倒着做01背包
for (int j=maxm;j>=;j--)
if (j-w[i]>=) f2[i][j]=max(f2[i-][j],f2[i-][j-w[i]]+v[i]);
else f2[i][j]=f2[i-][j];
for (int i=;i<=q;i++)//开始回答问题
{
ans=;
for (int j=;j<=e[i];j++)//枚举分配给左边多少钱
ans=max(ans,f[l[d[i]]-][j]+f2[now-r[d[i]]][e[i]-j]);
//这个可以去推一下l[d[i]]-1表示被删物品的前一个物品在f背包中的结束位置,now-r[d[i]]表示被删物品的后一个物品在f2背包中的开始位置。
printf("%d\n",ans);
}
return ;
}

好啦

3163: [Heoi2013]Eden的新背包问题的更多相关文章

  1. BZOJ 3163: [Heoi2013]Eden的新背包问题( 背包dp )

    从左到右, 从右到左分别dp一次, 然后就可以回答询问了. ---------------------------------------------------------- #include< ...

  2. bzoj 3163: [Heoi2013]Eden的新背包问题

    Description "寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听."失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的 ...

  3. BZOJ3163&Codevs1886: [Heoi2013]Eden的新背包问题[分治优化dp]

    3163: [Heoi2013]Eden的新背包问题 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 428  Solved: 277[Submit][ ...

  4. P4095 [HEOI2013]Eden 的新背包问题

    P4095 [HEOI2013]Eden 的新背包问题 题解 既然假定第 i 个物品不可以选,那么我们就设置两个数组 dpl[][] 正序选前i个物品,dpr[][] 倒序选前i个物品 ,价格不超过 ...

  5. luogu P4095 [HEOI2013]Eden 的新背包问题 多重背包 背包的合并

    LINK:Eden 的新背包问题 就是一个多重背包 每次去掉一个物品 询问钱数为w所能买到的最大值. 可以对于每次Q暴力dp 利用单调队列优化多重背包 这样复杂度是Qnm的. 发现过不了n==10的点 ...

  6. bzoj3163: [Heoi2013]Eden的新背包问题

    Description “寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听.”失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的感觉,却不能回忆起她 ...

  7. LUOGU P4095 [HEOI2013]Eden 的新背包问题

    题目描述 " 寄 没 有 地 址 的 信 ,这 样 的 情 绪 有 种 距 离 ,你 放 着 谁 的 歌 曲 ,是 怎 样 的 心 情 . 能 不 能 说 给 我 听 ." 失忆的 ...

  8. 题解——洛谷P4095 [HEOI2013]Eden 的新背包问题(背包)

    思路很妙的背包 用了一些前缀和的思想 去掉了一个物品,我们可以从前i-1个和后i+1个推出答案 奇妙的思路 #include <cstdio> #include <algorithm ...

  9. Luogu P4095 [HEOI2013]Eden 的新背包问题 思维/动规

    当时一直在想前缀和...多亏张队提醒... 从1到n背次包,保存每一个状态下的价值,就是不要把第一维压掉:再从n到1背一次,同样记住每种状态: 然后询问时相当于是max(前缀+后缀),当然前缀后缀中间 ...

随机推荐

  1. ORACLE 10G 闪回建议

    Flashback Tips The following tips and restrictions apply to using flashback features. Flashback Tips ...

  2. Android事件分发机制(一) Touch 事件的分发和消费机制

    Android 中与 Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent ev). ...

  3. 元素JS拖动的实现

    涉及到了几个位置的属性 offset   clientX cilentY 等 $(selector).on("mousedown",function (e){ var x = e. ...

  4. (Hibernate进阶)Hibernate基本原理(一)

    在开始学hibernate之前,一直就有人说:Hibernate并不难,无非是对JDBC进一步封装.一句不难,难道是真的不难还是眼高手低? 如果只是停留在使用的层面上,我相信什么技术都不难,看看别人怎 ...

  5. unity3d InverseTransformPoint方法

    从歪果仁的脚本里看到了这个方法,查脚本,看脚本说明也没看懂,官方的说明是,变换位置从世界坐标到自身坐标,Transform.TransformPoint相反. 试验了一下得出这个结论,如果某一个物体A ...

  6. c# 文件夾操作

    #region 圖片對應異動           string newFilePath = "~/FileUpLoad/Book/" + bookModel.BookNo;     ...

  7. 【转】你真的理解Python中MRO算法吗?

    你真的理解Python中MRO算法吗? MRO(Method Resolution Order):方法解析顺序. Python语言包含了很多优秀的特性,其中多重继承就是其中之一,但是多重继承会引发很多 ...

  8. Windows7 IE10运行不了JavaScript的问题

    如题,我的环境是Windows7 + IE10,JavaScript怎么也运行不了.郁闷了好一段时间. 后来发现一种办法终于可以让JavaScript运行起来. 具体:  点击 [工具] => ...

  9. modelsim(2) - vcd (dump, 查看,格式理解)

    二 vcd dump 由于VCD可以用于做功耗分析,所以需要把其dump出来.另外VCD可以作为结果,也可以作为激励,但是实际看到的少啊! VCD是verilog的标准,所以有系统函数$dumpvar ...

  10. iptables转发

    需求 将流入服务器的公网IP的80端口的流量全部转发到另一个公网IP(1.2.3.4)的80端口上. 操作 iptables -P FORWARD ACCEPT iptables -t nat -A ...