【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);
}

後記

博觀而約取,厚積而薄發。

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