分析
题意就是在 n 双鞋里买 k 双,有一些优惠方式可以使你少付一些鞋子的钱,计算最少的花费。
我们发现 k 很小,因此建立在它上面思考,我们又发现买入的鞋子为严格的 k 双,因此这道题就得到了极大的简化。鞋子数我们只需要留下最便宜的 k 双,优惠方案我们只需要留下 x 范围在 k 之内的最优的 y。
因此,n 和 m 都被我们缩到了 k 的范围,因此我们外层枚举剩余需要买的鞋子数,然后内层枚举优惠方案,\(k^2\) 转移解决此题。
#include<bits/stdc++.h>
using namespace std;
int v[2005],n,m,k,a[200005],f[2001],b[2005];
inline int min(int aa,int bb){return aa<bb?aa:bb;}
inline int max(int aa,int bb){return aa>bb?aa:bb;}
inline void read(int &res){
res=0;
char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
}
int main()
{
read(n);read(m);read(k);
memset(f,127,sizeof(f));
f[k]=0;//初始化
for(int i=1;i<=n;i++)read(a[i]);
sort(a+1,a+n+1);//找出前n小的方案
for(int i=1;i<=k;i++)b[i]=b[i-1]+a[i];//前缀处理转移
for(int i=1;i<=m;i++){
int x,y;
read(x);read(y);
if(x>k)continue;
v[x]=max(v[x],y);//存储在买x双的情况下最多能省多少双
}
for(int i=k-1;i>=0;i--){
for(int j=1;j<=k-i;j++){
f[i]=min(f[i],f[j+i]+b[i+j]-b[i+v[j]]);//转移
}
}
cout<<f[0]<<endl;
return 0;
}