Codeforces Round #552 (Div. 3) F题

题目网址:http://codeforces.com/contest/1154/problem/F

题目大意:给出n,m,k,n是物体的个数,m是优惠方式的种数,k是需要购买的物体个数,

然后给出n个数,即每个物体的价格,再给出m行,每行x,y,表示一种优惠方式,即,当你购买x

个物体时,前y个最便宜的物体免费,问,只有一种优惠方式时,需要花费的最少的钱。

题解:首先,要买k个物体,显然选择的物体价格是前k个最小的数,然后再考虑优惠,那么,购买k

个物体的最小价格是总价格减去购买前k个物体的最大花费,设dp1 [ i ] 是购买前i个物体的最大优惠,

那么在这i个物体中就可以考虑题目给的优惠方式了,设dp2[ i ]是购买了i个物体,最多可以减少物体的数量

那么对于前i个物体,优惠就是dp1[ i ]和dp1[ j ]+s[ j + dp2[ i - j ] ] - s[ j ]),sum这里是 i - j这部分物体的价钱,因为

我买了前j个物体,此时最大优惠是dp1[ j ],然后剩下的 i - j个物体的优惠是可以减少dp2[ i - j ]个物体的数量

所以剩下的 i - j个 物体只需s[ j + dp2[ i - j ] ] - s[ j ],最后总价格减去最大优惠价格即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=2e5+7;
 4 int a[maxn],s[maxn],dp1[maxn],dp2[maxn];
 5 int main()
 6 {
 7     int n,m,k,x,y;
 8     cin>>n>>m>>k;
 9     memset(dp1,0,sizeof(dp1));
10     memset(dp2,0,sizeof(dp2));
11     for(int i=1;i<=n;i++)
12     {
13         scanf("%d",&a[i]);
14     }
15     for(int i=1;i<=m;i++)
16     {
17         scanf("%d %d",&x,&y);
18         if(x<=k) dp2[x]=max(dp2[x],y);
19     }
20     sort(a+1,a+1+n);
21     for(int i=1;i<=k;i++) s[i]=s[i-1]+a[i];
22     for(int i=1;i<=k;i++)
23     {
24         for(int j=0;j<i;j++)
25         {
26             dp1[i]=max(dp1[i],dp1[j]+s[j+dp2[i-j]]-s[j]);
27         }
28     }
29     cout<<s[k]-dp1[k]<<endl;
30     return 0;
31 }
View Code

 

posted @ 2019-04-17 22:37  duxing201806  阅读(62)  评论(0编辑  收藏  举报