zoukankan      html  css  js  c++  java
  • DSY3163*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
     
    首先,如果不考虑多次询问和去掉某个玩偶,这是一个多重背包,将其转化为01背包再加上二进制优化,否则会炸内存。然后我们在考虑多个容量和去掉的问题,当去掉某个玩偶k后,相当于在1~k-1和k+1~n中做背包,那么需要倒着做一个正着做一个,也就是变为简单的01背包做两遍。最后询问时要枚举k两边的背包容量如何分配。不能压缩为一维数组。
    PS:这题输入输出如果用cin,cout平台上就会显示RE,不知道为什么……
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstdlib>
     4 using namespace std;
     5 int f[10010][1010]={0},f2[10010][1010]={0},a[1111]={0},b[1111]={0},c[1111]={0},d[300005]={0},e[300005]={0},v[10010]={0},w[10010]={0};
     6 int s[1111]={0};
     7 int main()
     8 {
     9     int n=0,q=0,tot;
    10     scanf("%d",&n);
    11     for (int i=1;i<=n;i++)
    12       scanf("%d%d%d",&a[i],&b[i],&c[i]);
    13     tot=0;
    14     int now=1,x=0,t=0;
    15     while (now<=n)//二进制优化
    16     {
    17         x=1;
    18         t=c[now];
    19         while (t-x>0)
    20         {
    21             ++tot;
    22             w[tot]=x*a[now];
    23             v[tot]=x*b[now];
    24             t-=x;
    25             x=x*2;
    26         }
    27         if (t>0)
    28         {
    29             ++tot;
    30             v[tot]=t*b[now];
    31             w[tot]=t*a[now];
    32         }
    33         s[now]=tot;
    34         ++now;
    35     }
    36     cin>>q;
    37     int me=0;
    38     for (int i=1;i<=q;++i)//寻找询问中最大的容量
    39     {
    40         scanf("%d%d",&d[i],&e[i]);
    41         d[i]+=1;
    42         if (e[i]>me)
    43           me=e[i];
    44     }
    45     for (int i=1;i<=tot;++i)//正着
    46       for (int j=0;j<=me;++j)
    47         if (j<w[i])
    48           f[i][j]=f[i-1][j];
    49         else f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
    50     for (int i=tot;i>=1;i--)//倒着
    51       for (int j=0;j<=me;++j)
    52         if (j<w[i])
    53           f2[i][j]=f2[i+1][j];
    54         else f2[i][j]=max(f2[i+1][j],f2[i+1][j-w[i]]+v[i]);
    55     int ans=0;
    56     for (int i=1;i<=q;++i)
    57     { 
    58       ans=0;
    59       for (int j=0;j<=e[i];++j)//枚举两边的容量如何分配
    60         if (f[s[d[i]-1]][j]+f2[s[d[i]]+1][e[i]-j]>ans)
    61           ans=f[s[d[i]-1]][j]+f2[s[d[i]]+1][e[i]-j];
    62       printf("%d
    ",ans);
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    JavaScript基础
    w3c网站案例
    CSS基础
    HTML基础
    MySQL--用户管理 pymysql 索引
    MySQL--高级
    MySQL--多表查询
    MySQL--单表查询
    直接插入排序与折半插入排序分析
    Nginx从安装到简单使用
  • 原文地址:https://www.cnblogs.com/Maxxzy/p/6228636.html
Copyright © 2011-2022 走看看