bzoj 3163: [Heoi2013]Eden的新背包问题
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
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
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。可以证明没有更优的方案了。注意买某种玩偶不一定要买光。
100. 数据满足1 ≤ n ≤ 1000, 1 ≤ q ≤ 3*105 , 1 ≤ a
i、bi、c i ≤ 100, 0 ≤ d i < n, 0 ≤ei ≤ 1000。
Source
http://www.lydsy.com/JudgeOnline/problem.php?id=3163
这道题和2287 消失之物 差不多
最大的隐患还是会超时。
算法用多重背包
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cstdio> 6 using namespace std; 7 int n,t,x,y,z,maxm,now,ans,q; 8 int d[400000],e[400000],w[30000],v[30000],l[2000],r[2000],f[10000][2000],f2[10000][2000]; 9 int max(int a,int b) 10 { 11 return (a>b?a:b); 12 } 13 int main() 14 { 15 //freopen("3163.in","r",stdin); 16 //freopen("3163.out","w",stdout); 17 scanf("%d",&n); 18 now=1; 19 for (int i=1;i<=n;i++) 20 { 21 t=1; 22 l[i]=now; 23 scanf("%d%d%d",&x,&y,&z); 24 while ((t*2-1)<z) 25 { 26 w[now]=t*x; 27 v[now]=t*y; 28 t*=2; 29 now+=1; 30 } 31 w[now]=(z-t+1)*x; 32 v[now]=(z-t+1)*y; 33 r[i]=now; 34 now+=1; 35 } 36 scanf("%d",&q); 37 for (int i=1;i<=q;i++) 38 { 39 scanf("%d%d",&d[i],&e[i]); 40 d[i]+=1; 41 if (e[i]>maxm) maxm=e[i]; 42 } 43 for (int i=1;i<=now;i++) 44 for (int j=maxm;j>=0;j--) 45 if (j-w[i]>=0) f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]); 46 else f[i][j]=f[i-1][j]; 47 for (int i=1;i<=now/2;i++) 48 { 49 t=w[i]; w[i]=w[now-i+1];w[now-i+1]=t; 50 t=v[i]; v[i]=v[now-i+1];v[now-i+1]=t; 51 } 52 for (int i=1;i<=now;i++) 53 for (int j=maxm;j>=0;j--) 54 if (j-w[i]>=0) f2[i][j]=max(f2[i-1][j],f2[i-1][j-w[i]]+v[i]); 55 else f2[i][j]=f2[i-1][j]; 56 for (int i=1;i<=q;i++) 57 { 58 ans=0; 59 for (int j=0;j<=e[i];j++) 60 ans=max(ans,f[l[d[i]]-1][j]+f2[now-r[d[i]]][e[i]-j]); 61 printf("%d\n",ans); 62 } 63 return 0; 64 }