分析

题意就是在 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;
}
posted on 2021-08-28 21:09  漠寒·  阅读(22)  评论(0编辑  收藏  举报