2020年蓝桥杯国赛-答疑

题目

题目链接

题解

贪心。


有点像“排队打水”。

比较好想,而且我甚至都能证明。


贪心思路:按照 s + a + e s+a+e s+a+e 从小到大排序即可。

证明:

首先,每个人的 s s s a a a 都可以看成是一个部分,记为 d d d,因为这段时间只是干的事不同,本质都是打卡前花费的时间。

规定 p i p_i pi 表示第 i i i个人, a i a_i ai b i b_i bi 分别对应第 i i i个人的 d d d e e e

排好序后为 P 1 P 2 . . . P i P i + 1 . . . P n P_1P_2...P_iP_{i+1}...P_n P1P2...PiPi+1...Pn,为了方便令 j = i + 1 j=i+1 j=i+1

显然无论是否交换 P i P_i Pi P j P_j Pj 的顺序都不会影响二者以外的人的打卡时间,所以变化的就只有二者的打卡时间,从而影响最终结果。

假设除 i 、 j i、j ij外的人的打卡时间之和记为 S S S,答案应为 S + S+ S+ P i P_i Pi 打卡时间 + P j +P_j +Pj 打卡时间。

a 1 + b 1 + a 2 + b 2 + . . . + a i − 1 + b i − 1 a_1+b_1+a_2+b_2+...+a_{i-1}+b_{i-1} a1+b1+a2+b2+...+ai1+bi1 S i − 1 S_{i-1} Si1,交换顺序前, P i P_i Pi 打卡的时间为 S i − 1 + a i S_{i-1}+a_i Si1+ai P j P_j Pj 的打卡时间为 S i − 1 + a i + b i + a j S_{i-1}+a_i+b_i+a_j Si1+ai+bi+aj,对应答案为 S + ( S i − 1 + a i ) + ( S i − 1 + a i + b i + a j ) S+(S_{i-1}+a_i)+(S_{i-1}+a_i+b_i+a_j) S+(Si1+ai)+(Si1+ai+bi+aj);交换顺序后,即序列为 P 1 P 2 . . . P j P i . . . P n P_1P_2...P_jP_{i}...P_n P1P2...PjPi...Pn,那么 P i P_i Pi 打卡的时间为 S i − 1 + a j + b j + a i S_{i-1}+a_j+b_j+a_i Si1+aj+bj+ai P j P_j Pj 的打卡时间为 S i − 1 + a j S_{i-1}+a_j Si1+aj,对应答案为 S + ( S i − 1 + a j + b j + a i ) + ( S i − 1 + a j ) S+(S_{i-1}+a_j+b_j+a_i)+(S_{i-1}+a_j) S+(Si1+aj+bj+ai)+(Si1+aj)

a i + b i a_i+b_i ai+bi 记为 s u m i sum_i sumi a j + b j a_j+b_j aj+bj 记为 s u m j sum_j sumj,则交换前答案为 S + 2 S i + s u m i + a i + a j S+2S_i+sum_i+a_i+a_j S+2Si+sumi+ai+aj,交换后答案为 S + 2 S i + s u m j + a i + a j S+2S_i+sum_j+a_i+a_j S+2Si+sumj+ai+aj。可见,影响最终答案的是 s u m i sum_i sumi s u m j sum_j sumj 的大小关系。

最终可以判断 s u m sum sum 小的在前更佳,即 a + b a+b a+b 小的,又即 s + a + e s+a+e s+a+e 小的。

(总而言之,就是交换法证明贪心,最简单的证明了)

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL ans = 0, sum = 0;
int n;

const int N = 1100;

struct node {
	int a, b, c, d;
} s[N];

bool cmp (node a, node b) {
	return a.d < b.d;
}

int main()
{
	cin >> n;
	for (int i = 0;i < n;i ++) 
		cin >> s[i].a >> s[i].b >> s[i].c, 
		s[i].d = s[i].a + s[i].b + s[i].c;
	
	sort (s, s + n, cmp);
	
	for (int i = 0;i < n;i ++) 
	ans += sum + s[i].a + s[i].b,
	sum += s[i].d;

	cout << ans << endl;
	return 0;
}
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不牌不改

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值