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

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。可以证明没有更优的方案了。注意买某种玩偶不一定要买光。


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
",ans);
62    }
63    return 0;
64 }
原文地址:https://www.cnblogs.com/lztlztlzt/p/6245087.html