(第十一届蓝桥杯总决赛)H:答疑(贪心)

题目链接:“蓝桥杯”练习系统

 

分析:这道题目我感觉题意叙述上有点问题,题目中说一位同学需要准备s秒时间进入办公室,离开办公室需要e秒时间,他只说进入办公室需要准备s秒并没有说在上一位同学发出消息后到离开办公室前这段时间内不能准备,所以就导致了我一直没能想出来正确思路。也希望大家能够注意这一点。

下面来进行正确的思路分析

假设最优的安排答疑顺序是1,2,3……,n,每个编号代表一个同学

那么1号同学发消息的时刻就是s1+a1

2号同学发消息的时刻就是s1+a1+e1+s2+a2

3号同学发消息的时刻就是s1+a1+e1+s2+a2+e2+s3+a3

……

n号同学发消息的时刻就是s1+a1+e1+s2+a2+e2+s3+a3+e3+……+s(n-1)+a(n-1)+e(n-1)+sn+an

把这n位同学发消息的时刻加起来就是\sum_{i=1}^{n}((n-i+1)*(si+ai))+\sum_{i=1}^{n}((n-i)*ei),化简后得到\sum_{i=1}^{n}((n-i)*(si+ai+ei))+\sum_{i=1}^{n}(si+ai),右边的求和值是固定的,不会随着顺序的变化而变化,而左边中si+ai+ei对于每个数也是固定的,只是每个和被计算的次数不一样,越靠前面的被计算的次数越多,所以应该把s和a和e三个数的和较小的编号放在前面,这就是本道题目的贪心策略

下面是代码:
 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1300;
struct node{
	int s,a,e;
}p[N];
bool cmp(node a,node b)
{
	return (a.a+a.e+a.s)<(b.a+b.e+b.s);
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		scanf("%d%d%d",&p[i].s,&p[i].a,&p[i].e);
	sort(p+1,p+n+1,cmp);
	long long ans=0;
	for(int i=1;i<=n;i++)
		ans+=(n-i)*(p[i].a+p[i].e+p[i].s)+p[i].a+p[i].s;
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/AC__dream/article/details/124025236