zoukankan      html  css  js  c++  java
  • 【dp】E. Selling Souvenirs

    http://codeforces.com/contest/808/problem/E

    题意:给定n个重量为可能1,2,3的纪念品和各自的价值,问在背包总重量不超过m的条件下总价值最大为多少。

    其中1 ≤ n ≤ 100000, 1 ≤ m ≤ 300000

    首先可以想到的是重量相同的情况下,优先选择价值大的纪念品。所以我们可以把价值为1,2,3的纪念品分开,分别排序。

    我们可以枚举重量为3的纪念品的个数为x,然后剩下的重量m-sum{3-elements}由1和2混合得出,这里可以动态规划预处理。

    dp[i]是一个三元组{cost,cnt1,cnt2},分别表示重量为i的情况下的最大价值,以及这时候1和2分别用了多少。

    dp[i]可以dp[i-1]和dp[i-2]推出。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<string>
      5 #include<algorithm>
      6 #include<cmath>
      7 #include<set>
      8 #include<map> 
      9 #include<utility> 
     10 using namespace std;
     11 typedef long long ll;
     12 const int maxn=3e5+2;
     13 
     14 struct node
     15 {
     16     ll cost;
     17     int cnt1;
     18     int cnt2;
     19 }dp[maxn];
     20 ll sum[maxn];
     21 ll a[maxn],b[maxn],c[maxn];
     22 int n,m;
     23 int main()
     24 {
     25     scanf("%d%d",&n,&m);
     26     int weight;
     27     ll cost;
     28     int p=0,q=0,r=0;
     29     for(int i=0;i<n;i++)
     30     {
     31     //    scanf("%d%lld",&weight,&cost);
     32         cin>>weight>>cost; 
     33         if(weight==1)
     34         {
     35             a[p++]=cost;
     36         }
     37         else if(weight==2)
     38         {
     39             b[q++]=cost;
     40         }
     41         else
     42         {
     43             c[r++]=cost;
     44         }
     45     }
     46     sort(a,a+p);
     47     sort(b,b+q);
     48     sort(c,c+r);
     49     dp[0].cost=0;
     50     dp[0].cnt1=p;
     51     dp[0].cnt2=q;
     52     dp[1].cost=a[p-1];
     53     dp[1].cnt1=p-1;
     54     dp[1].cnt2=q;
     55     for(int i=2;i<=m;i++)
     56     {
     57         if(dp[i-1].cnt1-1>=0&&dp[i-2].cnt2-1>=0)
     58         {
     59             if(dp[i-1].cost+a[dp[i-1].cnt1-1]>dp[i-2].cost+b[dp[i-2].cnt2-1])
     60             {
     61                 dp[i].cost=dp[i-1].cost+a[dp[i-1].cnt1-1];
     62                 dp[i].cnt1=dp[i-1].cnt1-1;
     63                 dp[i].cnt2=dp[i-1].cnt2;
     64             }
     65             else
     66             {
     67                 dp[i].cost=dp[i-2].cost+b[dp[i-2].cnt2-1];
     68                 dp[i].cnt1=dp[i-2].cnt1;
     69                 dp[i].cnt2=dp[i-2].cnt2-1;
     70             }
     71         }
     72         else if(dp[i-1].cnt1-1<0&&dp[i-2].cnt2-1>=0)
     73         {
     74             dp[i].cost=dp[i-2].cost+b[dp[i-2].cnt2-1];
     75                 dp[i].cnt1=dp[i-2].cnt1;
     76                 dp[i].cnt2=dp[i-2].cnt2-1;
     77         }
     78         else if(dp[i-1].cnt1-1>=0&&dp[i-2].cnt2-1<0)
     79         {
     80             dp[i].cost=dp[i-1].cost+a[dp[i-1].cnt1-1];
     81                 dp[i].cnt1=dp[i-1].cnt1-1;
     82                 dp[i].cnt2=dp[i-1].cnt2;
     83         }
     84         else
     85         {
     86             break;
     87         }
     88     }
     89     sum[r]=0;
     90     for(int i=r-1;i>=0;i--)
     91     {
     92         sum[i]=sum[i+1]+c[i];
     93     }
     94     ll ans=0;
     95     for(int i=0;i<=m;i++)
     96     {
     97         int x=(m-i)/3;
     98         ll temp=dp[i].cost+sum[max(r-x,0)];
     99         if(temp>ans)
    100         {
    101             ans=temp;
    102         }
    103     }
    104     cout<<ans<<endl; 
    105     
    106     
    107     return 0;
    108 }
    View Code

     注意一些小细节:

    1 ll temp=dp[i].cost+sum[max(r-x,0)];
    重量为3的可能不够用
  • 相关阅读:
    Grodno 2015 (Urozero May 2015 Day 5) D Triangles
    Flea Circus(Project Euler 213)
    Prime triplets (Project Euler 196)
    ACM 博弈(难)题练习 (第二弹)
    Crosses Puzzles zoj 4018 (zju校赛)
    Petrozavodsk Summer-2015. Ivan Smirnov Contest 1 B Bloom
    ACM 博弈(难)题练习 (第一弹)
    2017 ACM区域赛(南宁站) 参赛流水账
    2017 CCPC 杭州 流水账
    2017 ACM区域赛(西安) 参赛流水账
  • 原文地址:https://www.cnblogs.com/itcsl/p/6873507.html
Copyright © 2011-2022 走看看