原题链接: https://codeforces.com/problemset/problem/1379/C
测试样例:
Input
2
4 3
5 0
1 4
2 2
5 3
5 2
4 2
3 1
Output
14
16
样例解释:
In the first example case Vladimir can pick 1 flower of the first type and 3 flowers of the second type, in this case the total happiness equals 5+(1+2⋅4)=14.
In the second example Vladimir can pick 2 flowers of the first type, 2 flowers of the second type, and 1 flower of the third type, in this case the total happiness equals (5+1⋅2)+(4+1⋅2)+3=16.
题意: 给定种鲜花的信息:购买第
种花
朵所得的价值为
,问你购买
朵鲜花所获得的最大价值。
解题思路: 我们先来分析一下这道题目,总共有m种花,我们如果买一朵得到的价值就是,那么不会考虑到
。如果我们这朵花我们之前买过,则我们获得的价值就为
,那么我们可以推断一下,我们购买的最优方案花的数量大于1的花只有一种。因为如果你购买的超过两种,那么我们完全可以选择那个
值比较大的进行操作。所以我们可知我们的购买方案花的数量大于1的只有一种。OK,那么我们就可以枚举我们所购买的数量大于1的那一种花。然后对于此花,我们的最优购买方案是先把其他花价值
大于这个
的都买掉,最后再全部购买
,这就是最优方案。那么,我们要取所有枚举结果的最大值即可。具体看代码。
AC代码:
/*
、
*/
//POJ不支持
//i为循环变量,a为初始值,n为界限值,递增
//i为循环变量, a为初始值,n为界限值,递减。
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5+2;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//
int t,n,m;
struct node{
ll a,b;
}nums[maxn];
ll c[maxn],sum[maxn];
int main(){
//freopen("in.txt", "r", stdin);//提交的时候要注释掉
IOS;
while(cin>>t){
while(t--){
cin>>n>>m;
rep(i,1,m){
cin>>nums[i].a>>nums[i].b;
c[i]=nums[i].a;
}
sort(c+1,c+1+m);
sum[0]=0;
rep(i,1,m){
sum[i]=sum[i-1]+c[i];
}
ll ans=0,temp,pos,len,q;
rep(i,1,m){
temp=0;q=n;
pos=lower_bound(c+1,c+1+m,nums[i].b)-c;
len=min(q,m-pos+1); //获取我们要买的数目。
temp+=sum[m]-sum[m-len];
q-=len;
if(q>0){
if(c[pos]>nums[i].a||pos==m+1){
temp+=nums[i].a;
q--;
}
temp+=nums[i].b*q;
}
ans=max(ans,temp);
}
cout<<ans<<endl;
}
}
return 0;
}