題意
給出 個二維座標點,要求給出兩個點的編號滿足此兩點間距離最遠,僅允許走 度斜邊與網格邊。
思路
此題僅允許走斜邊與網格邊,而非最短路徑,因此不同於之前僅考慮最短路徑的做法,即求凸包直徑。(不過此題直接求凸包直徑貌似也能過,應該是因爲此種新定義的路徑與絕對路徑間的差值不大有關)
此題求法非常巧妙,我們可以先列舉下述四種情況,對整體題目有一個大致把握。
上述四種情況中,紅色邊爲真實路徑,因此我們可以列出路徑的計算公式如下。
此四種情況即爲本題計算答案時所有的情況,不難發現,對於情況一來說,如果採用的公式非公式 ,則 會變小,即對於每一種情況來說,只有使用其情況所對應的公式才能獲得最大的 值,所以我們可以對於上述的四種情況分別計算。
以情況 爲例,每次選取 的最大值和最小值,然後最大值減去最小值即爲該情況下的兩點距離最大值。
總結
此做法不單適應於本題,如果題目改爲只能走網格邊或者變成切比雪夫座標系,本做法都可以非常簡單地解決。因此該做法的思想比較精妙,需要掌握!
代碼
#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);
}
後記
博觀而約取,厚積而薄發。