• 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 }
  • 相关阅读:
    Python学习笔记Day08
    Python学习笔记Day06~07
    Python学习笔记Day05
    linux文件属性之用户和组基础知识
    linux文件属性之linux文件删除原理
    linux文件属性软硬链接知识
    linux文件属性文文件类型知识
    linux文件属性描述(inode,block)
    xargs命令
    find命令
  • 原文地址:https://www.cnblogs.com/lztlztlzt/p/6245087.html
Copyright © 2020-2023  润新知