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 ],最后总价格减去最大优惠价格即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }