Solution -「P2672」推销员

cirnovsky /

∆ 首先,这是一道贪心的绝世好题

§ 其次,这道题要用到结构体这门高深的知识

☆ 最后,这道题我样例2没有过但是我交了4个OJ都AC了

??????????????????_______????????????????????

不bb了,上思路吧

这道题主要用到了瞪眼大法以及贪心大法

我们可以记录下往返距离加上自身疲劳值最高的一个崽儿,以下就简称ze。

然后通过观察样例,可以发现ze每次都会参与输出,即每次都会向ze这个点进行推销,但不一定每次都把ze这个点当作终点。因为我们的排序规则是往返距离加上自身疲劳值按降序进行排序,所以ze不一定就是最远的那一户人家。

通过以上的瞪眼观察,我们发现,既然每一次都会有ze这个点,那么我们就可以划分子问题了,符合了贪心的定义。

其实这个思路也不是我独立思考出来的,而是我们机房大佬写了一篇题解。 但是这篇题解简直不要太精简,我是完全没有看懂。而代码我也没有去看

§ 给大家观摩一下:

一道贪心的题

其实找到距离较远但疲劳值(往返+当前位置的疲劳值)最大的那个位置

让它C位出道

再排序排出疲劳值高的

前缀和+当前最远距离*2

不知道大家看懂没有,反正我这个人一向看不懂别人的思路。不过这也给了我一点启发

Q:为什么不用DP?

A:因为DP会超时,而且看这道题目只是15年普及组的T3,用不着

你们最爱的完整代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define Inf 0x3f3f3f3f

using namespace std;

const int MAXN = 100000 + 5;
struct Node {
	int Far, Cost;
} a[MAXN];
int n, maxValue, list[MAXN];
inline bool Rule(const Node &a, const Node &b)
	{ return ((a.Cost == b.Cost) && (a.Far > b.Far)) || (a.Cost > b.Cost); }

signed main() {
	scanf("%d", &n);
	for (register int i = 1; i <= n; ++i) scanf("%d", &a[i].Far);
	for (register int i = 1; i <= n; ++i) {
		scanf("%d", &a[i].Cost);
		if ((a[i].Far << 1) + a[i].Cost > (a[maxValue].Far << 1) + a[i].Cost)
			maxValue = i;
	}
	
	a[0] = a[maxValue];
	a[maxValue] = Node{-Inf, -Inf};
	stable_sort(a + 1, a + 1 + n, Rule);

	for (register int i = 0; i < n; ++i)
		list[i] = max(list[i - 1], a[i].Far);
	int and_ = 0;
	for (register int i = 0; i < n; ++i) {
		and_ += a[i].Cost;
		printf("%d\n", and_ + (list[i] << 1));
	}
	return 0;
}