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 ],最后总价格减去最大优惠价格即可。

 #include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+;
int a[maxn],s[maxn],dp1[maxn],dp2[maxn];
int main()
{
int n,m,k,x,y;
cin>>n>>m>>k;
memset(dp1,,sizeof(dp1));
memset(dp2,,sizeof(dp2));
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=;i<=m;i++)
{
scanf("%d %d",&x,&y);
if(x<=k) dp2[x]=max(dp2[x],y);
}
sort(a+,a++n);
for(int i=;i<=k;i++) s[i]=s[i-]+a[i];
for(int i=;i<=k;i++)
{
for(int j=;j<i;j++)
{
dp1[i]=max(dp1[i],dp1[j]+s[j+dp2[i-j]]-s[j]);
}
}
cout<<s[k]-dp1[k]<<endl;
return ;
}
上一篇:NGINX Plus 提供的在线活动监控功能


下一篇:【新功能】弹性公网IP绑定弹性网卡新功能及最佳实践