HDU 1392 Surround the Trees(凸包)題解
阿新 • • 發佈:2019-02-21
code esp pos con clas tac span bool swa
題意:給一堆二維的點,問你最少用多少距離能把這些點都圍起來
思路:
凸包:
我們先找到所有點中最左下角的點p1,這個點絕對在凸包上。接下來對剩余點按照相對p1的角度升序排序,角度一樣按距離升序排序。因為凸包有一個特點,順時針走,所有線都在當前這條向量的右邊,根據這個特點我們進行判斷。我們從棧頂拿出兩個點s[top-1],s[top],所以如果s[top-1] -> p[i] 在 s[top-1] -> s[top] 左邊,那麽s[top]就不是凸包上一點,就這樣一直判斷下去。判斷左右可以用叉乘。
參考:數學:凸包算法詳解
模板(考慮n <= 2):
structnode{ double x, y; }p[maxn], s[maxn]; int n, top; double dis(node a, node b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } bool cmp(node a, node b){ double A = atan2((a.y - p[1].y), (a.x - p[1].x)); double B = atan2((b.y - p[1].y), (b.x - p[1].x));if(A != B) return A < B; else{ return dis(a, p[1]) < dis(b, p[1]); } } double cross(node a, node b, node c){ //(a->b)X(a->c) return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); } void solve(){ int pos = 1; for(int i = 2; i <= n; i++){if(p[i].y < p[pos].y || (p[i].y == p[pos].y && p[i].x < p[pos].x)){ pos = i; } } swap(p[1], p[pos]); sort(p + 2, p + n + 1, cmp); s[0] = p[1], s[1] = p[2]; top = 1; for(int i = 3; i <= n; i++){ while(top >= 1 && cross(s[top - 1], p[i], s[top]) >= 0){ //向左轉出棧 top--; } s[++top] = p[i]; } }
代碼:
#include<set> #include<map> #include<stack> #include<cmath> #include<queue> #include<vector> #include<string> #include<cstdio> #include<cstring> #include<sstream> #include<iostream> #include<algorithm> typedef long long ll; using namespace std; const int maxn = 150 + 10; const int MOD = 1e9 + 7; const int INF = 0x3f3f3f3f; struct node{ double x, y; }p[maxn], s[maxn]; int n, top; double dis(node a, node b){ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } bool cmp(node a, node b){ double A = atan2((a.y - p[1].y), (a.x - p[1].x)); double B = atan2((b.y - p[1].y), (b.x - p[1].x)); if(A != B) return A < B; else{ return dis(a, p[1]) < dis(b, p[1]); } } double cross(node a, node b, node c){ //(a->b)X(a->c) return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); } void solve(){ int pos = 1; for(int i = 2; i <= n; i++){ if(p[i].y < p[pos].y || (p[i].y == p[pos].y && p[i].x < p[pos].x)){ pos = i; } } swap(p[1], p[pos]); sort(p + 2, p + n + 1, cmp); s[0] = p[1], s[1] = p[2]; top = 1; for(int i = 3; i <= n; i++){ while(top >= 1 && cross(s[top - 1], p[i], s[top]) >= 0){ //向左轉出棧 top--; } s[++top] = p[i]; } } int main(){ while(~scanf("%d", &n) && n){ for(int i = 1; i <= n; i++){ scanf("%lf%lf", &p[i].x, &p[i].y); } if(n == 1){ printf("0.00\n"); continue; } if(n == 2){ printf("%.2lf\n", dis(p[1], p[2])); continue; } solve(); double ans = 0; for(int i = 0; i < top; i++){ ans += dis(s[i], s[i + 1]); } ans += dis(s[top], s[0]); printf("%.2lf\n", ans); } return 0; }
HDU 1392 Surround the Trees(凸包)題解