【2015 NEERC - G 】Garden Gathering【距离计算变形、数学巧妙转换】

题意

给出 nn 个二维座标点,要求给出两个点的编号满足此两点间距离最远,仅允许走 4545 度斜边与网格边。(2n2105,xi,yi107)(2\leq n\leq 2*10^5, |x_i|,|y_i|\leq 10^7)

题目链接:linklink


思路

此题仅允许走斜边与网格边,而非最短路径,因此不同于之前仅考虑最短路径的做法,即求凸包直径。(不过此题直接求凸包直径貌似也能过,应该是因为此种新定义的路径与绝对路径间的差值不大有关)

此题求法非常巧妙,我们可以先列举下述四种情况,对整体题目有一个大致把握。
在这里插入图片描述
上述四种情况中,红色边为真实路径,因此我们可以列出路径的计算公式如下。
(1) dis=[(21)x1+y1][(21)x2+y2](2) dis=[(21)x1y1][(21)x2y2](3) dis=[x1+(21)y1][x2+(21)y2](3) dis=[x1(21)y1][x2(21)y2] (1) \ dis = [(\sqrt2-1)*x_1+y_1]-[(\sqrt2-1)*x_2+y_2] \\ (2) \ dis = [(\sqrt2-1)*x_1-y_1]-[(\sqrt2-1)*x_2-y_2] \\ (3) \ dis = [x_1+(\sqrt2-1)*y_1]-[x_2+(\sqrt2-1)*y_2] \\ (3) \ dis = [x_1-(\sqrt2-1)*y_1]-[x_2-(\sqrt2-1)*y_2] \\
此四种情况即为本题计算答案时所有的情况,不难发现,对于情况一来说,如果采用的公式非公式 (1)(1),则 disdis 会变小,即对于每一种情况来说,只有使用其情况所对应的公式才能获得最大的 disdis 值,所以我们可以对于上述的四种情况分别计算。

以情况 (1)(1) 为例,每次选取 (21)x1+y1(\sqrt2-1)*x_1+y_1 的最大值和最小值,然后最大值减去最小值即为该情况下的两点距离最大值。


总结

此做法不单适应于本题,如果题目改为只能走网格边或者变成切比雪夫座标系,本做法都可以非常简单地解决。因此该做法的思想比较精妙,需要掌握!


代码

#include <bits/stdc++.h>
const int N = 2e5+100;
const double inf = 1e16;
const double E = sqrt(2)-1;
using namespace std;

double X[N], Y[N], ans, f[4][2] = {{E,1},{E,-1},{1,E},{1,-E}};
int n, p1, p2, id1, id2;

int main(){
	scanf("%d",&n);
	for(int i = 1; i <= n; i++) scanf("%lf%lf",&X[i],&Y[i]);
	for(int k = 0; k < 4; k++){
		double maxn = -inf, minn = inf;
		for(int i = 1; i <= n; i++){
			double cur = X[i] * f[k][0] + Y[i] * f[k][1];
			if(cur > maxn) maxn = cur, id1 = i;
			if(cur < minn) minn = cur, id2 = i;
		}
		if(ans < maxn-minn) ans = maxn-minn, p1 = id1, p2 = id2;
	}
	printf("%d %d\n", p1, p2);
}

后记

博观而约取,厚积而薄发。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章