中石油训练赛 - 奎奎发红包(贪心)

题目描述

情人节又到了,又到了一年一度发红包的时间。经大家研究决定,今年让奎奎自愿发红包。
俱乐部有n个人(0<n<100000),每个人都有一个单身值v[i]与亲密度t[i](0≤v[i]≤10000,0≤t[i]≤10000),单身值越大的人,在情人节的时候就越羡慕奎奎,奎奎就需要给他更大的红包来安慰他。 由于一个寒假没有见到奎奎,领红包的时候大家都想跟奎奎py,花费时间t[i],先py后给红包噢。
大家都厌倦了等待,如果一个人等了时间t,那么奎奎发给他的红包大小就是v[i]·t。
但是奎奎还要和女朋友去快乐,想要花最少的钱来满足大家。
请你帮他计算最少需要发多少钱的红包。

输入

第一行一个整数n。接下来n行,每行两个数v[i]和t[i]。

输出

一个整数表示答案。

样例输入 Copy

4
1 4
2 3
3 2
4 1

样例输出 Copy

35

题目分析:签到题贪心。。请教的ybl大佬,我真的太弱了

每个人都有两个属性 v[ i ] 和 t[ i ],考虑前后两个人,x 和 y 的相对位置:

  1. 如果 x 在前 y 在后:v[ x ] * t[ x ] + v[ y ] * ( t[ x ] + t[ y ] ) = v[ x ] * t[ x ] + v[ y ] * t[ x ] + v[ y ] * t[ y ]
  2. 如果 y 在前 x 在后:v[ y ] * t[ y ] + v[ x ] * ( t[ x ] + t[ y ] ) = v[ y ] * t[ y ] + v[ x ] * t[ x ] + v[ x ] * t[ y ]

也就是说,当 v[ x ] * t[ x ] + v[ y ] * t[ x ] + v[ y ] * t[ y ] < v[ y ] * t[ y ] + v[ x ] * t[ x ] + v[ x ] * t[ y ] 时,x 在前

可能这样看着还是有点乱,约分一下: v[ y ] * t[ x ] < v[ x ] * t[ y ] 时,x 在前

然后排序一下就好了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
       
typedef long long LL;
      
typedef unsigned long long ull;
       
const int inf=0x3f3f3f3f;
  
const int N=1e5+100;

struct Node
{
	int v,t;
	void input()
	{
		scanf("%d%d",&v,&t);
	}
	bool operator<(const Node& a)const
	{
		return a.v*t<a.t*v;
	}
}a[N];
 
int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		a[i].input();
	sort(a+1,a+1+n);
	LL ans=0,time=0;
	for(int i=1;i<=n;i++)
	{
		time+=a[i].t;
		ans+=time*a[i].v;
	}
	printf("%lld\n",ans);
	
	
	
	
	
	
	
	
	
	

    return 0;
}
发布了691 篇原创文章 · 获赞 27 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104748188
今日推荐