Bridge Across Islands POJ - 3608 旋轉卡殼求凸包最近距離
阿新 • • 發佈:2018-12-29
\(\color{#0066ff}{題目描述}\)
幾千年前,有一個小王國位於太平洋的中部。王國的領土由兩個分離的島嶼組成。由於洋流的衝擊,兩個島嶼的形狀都變成了凸多邊形。王國的國王想建立一座橋來連線這兩個島嶼。為了把成本降到最低,國王要求你,主教,找到兩個島嶼邊界之間最小的距離。
\(\color{#0066ff}{輸入格式}\)
輸入由幾個測試用例組成。
每個測試用兩個整數n,m(3≤n,m≤10000)開始
接下來的n行中的每一行都包含一對座標,用來描述頂點在一個凸多邊形中的位置。
下一條m線中的每一條都包含一對座標,它描述了一個頂點在另一個凸多邊形中的位置。
n=m=0的行表示輸入的結束。
座標在這個範圍內[-10000,10000]。
\(\color{#0066ff}{輸出格式}\)
對每個測試用例輸出最小距離。在0.001範圍內的錯誤是可以接受的
\(\color{#0066ff}{輸入樣例}\)
4 4
0.00000 0.00000
0.00000 1.00000
1.00000 1.00000
1.00000 0.00000
2.00000 0.00000
2.00000 1.00000
3.00000 1.00000
3.00000 0.00000
0 0
\(\color{#0066ff}{輸出樣例}\)
1.00000
\(\color{#0066ff}{資料範圍與提示}\)
none
\(\color{#0066ff}{題解}\)
旋轉卡殼
輸入的時候就是凸包,所以不用再求了
對於最近距離,可能是點點,點邊, 邊邊,這個可以在點到邊的距離那裡一併處理
距離可以通過面積判斷(底固定,高最大)
(叉積是負的,所以用<) 找到高最小的更新ans
#include <cstdio> #include <cmath> #include <cctype> #include <algorithm> #define _ 0 #define LL long long inline LL in() { LL x = 0, f = 1; char ch; while(!isdigit(ch = getchar()))(ch == '-') && (f = -f); while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = getchar(); return x * f; } const int maxn = 1e4 + 100; int n, m; struct node { double x, y; node(double x = 0, double y = 0) :x(x), y(y) {} node operator - (const node &b) const { return node(x - b.x, y - b.y); } double operator ^ (const node &b) const { return x * b.y - y * b.x; } double operator * (const node &b) const { return x * b.x + y * b.y; } double dis() { return sqrt(x * x + y * y); } double dis(const node &a, const node &b) { node c = *this; //垂足不線上段ab上 if((b - a) * (c - a) < 0) return (c - a).dis(); if((a - b) * (c - b) < 0) return (c - b).dis(); //平行四邊形面積 / 底 = 高 return fabs(((a - b) ^ (c - b)) / (a - b).dis()); } }A[maxn], B[maxn]; double Min(node a, node b, node c, node d) { return std::min(std::min(c.dis(a,b),d.dis(a,b)),std::min(a.dis(c,d),b.dis(c,d))); } double work() { double ans = 1e20; int min = 0, max = 0; for(int i = 0; i < n; i++) if(A[i].y < A[min].y) min = i; for(int i = 0; i < m; i++) if(B[i].y > B[max].y) max = i; A[n] = A[0], B[m] = B[0]; for(int i = 0; i < n; i++) { node t = A[min + 1] - A[min]; while((t ^ (B[max] - A[min])) < (t ^ (B[max + 1] - A[min]))) max = (max + 1) % m; ans = std::min(ans, Min(A[min], A[min + 1], B[max], B[max + 1])); min = (min + 1) % n; } return ans; } int main() { while("fuck") { n = in(), m = in(); if(!n && !m) break; for(int i = 0; i < n; i++) scanf("%lf%lf", &A[i].x, &A[i].y); for(int i = 0; i < m; i++) scanf("%lf%lf", &B[i].x, &B[i].y); printf("%.3f\n", work()); } return 0; }