// 2019.8.13
// 昨天的内容是计算几何部分点、线、多边形、向量、凸包等基本概念的介绍和模板的引入,之前的博客已有涉及,不再重复记录。
// 今天同样是ddy带来了计算几何进阶知识点的讲解。
凸包
凸包模板,HDU1392 求凸包周长
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int maxn = 110; typedef double db; struct P { db x, y; P(db x=0, db y=0):x(x), y(y) {} P operator-(const P& a) { return P(x-a.x, y-a.y); } P operator+(const P& a) { return P(x+a.x, y+a.y); } P operator*(const db a) { return P(a*x, a*y); } double len() { return sqrt(x*x+y*y); } void print() { printf("(%.2lf %.2lf)\n", x, y); } }node[maxn]; int n; // 向量a,b叉积 a×b db cross(const P& a, const P& b) { return a.x*b.y - b.x*a.y; } // 凸包 P stack[maxn]; int top; // 凸包上点个数 bool cmp(P a, P b) { db x = cross(a-node[0], b-node[0]); if(x>0) return 1; if(x==0) return (a-node[0]).len()<(b-node[0]).len(); return 0; } // 返回凸包上点的个数 // 点按逆时针放入stack double graham() { // 1. 找到最左下方的点 int k=0; for(int i=1;i<n;i++) { if(node[i].y<node[k].y || node[i].y==node[k].y && node[i].x<node[k].x) k = i; } swap(node[0], node[k]); // 2. 按照极角排序 sort(node+1, node+n, cmp); /* for(int i=0;i<n;i++) { node[i].print(); } */ // 3. 保存凸包上的点 stack[0] = node[0]; stack[1] = node[1]; int top = 1; for(int i=2;i<n;i++) { while(top>=1 && cross(stack[top]-stack[top-1], node[i]-stack[top-1])<=0) --top; stack[++top] = node[i]; } stack[++top] = stack[0]; double ans = 0; for(int i=1;i<=top;i++) { ans += (stack[i]-stack[i-1]).len(); } return ans; } int main() { while(scanf("%d", &n)!=EOF && n) { for(int i=0;i<n;i++) { scanf("%lf %lf", &node[i].x, &node[i].y); } if(n==1) printf("0.00\n"); // n==2居然要特判。。。什么傻逼 else if(n==2) printf("%.2lf\n", (node[0]-node[1]).len()); else printf("%.2lf\n", graham()); } return 0; }