《凸包》
本来都是不搞计算几何的..
但是由于斜率dp里要用到,所以被迫学一下。
定义:覆盖所有平面内的点的最小的凸多边形。
Graham算法:
以某个点为起点左右转移来维护凸包的边界的思路。
利用极角排序来对过程优化。且维护一个栈。
洛谷P2742
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> pii; const int N = 1e5 + 5; const int M = 5e5 + 5; const LL Mod = 1e9 + 7; #define pi acos(-1) #define INF 1e16 #define dbg(ax) cout << "now this num is " << ax << endl; int n; struct Point{ double x,y; double Distance(Point p1,Point p2) {//两点间距离 return sqrt((p2.y-p1.y) * (p2.y-p1.y) + (p2.x-p1.x) * (p2.x-p1.x)); } double check(Point a1,Point a2,Point b1,Point b2) {//检查叉积是否大于0,如果是a就逆时针转到b return (a2.x-a1.x) * (b2.y-b1.y) - (b2.x-b1.x) * (a2.y-a1.y); } }p[N],s[N]; bool cmp(Point p1,Point p2) { double tmp = p[0].check(p[1],p1,p[1],p2); if(tmp > 0) return true; if(tmp == 0 && p[0].Distance(p[0],p1) < p[0].Distance(p[0],p2)) return true; return false; } double Graham() { sort(p + 2,p + n + 1,cmp); s[1] = p[1];//最低点 int cnt = 1; for(int i = 2;i <= n;++i) { while(cnt > 1 && p[0].check(s[cnt - 1],s[cnt],s[cnt],p[i]) < 0) cnt--;//踢走栈顶 s[++cnt] = p[i]; } s[cnt + 1] = p[1]; double ans = 0; for(int i = 1;i <= cnt;++i) ans += p[0].Distance(s[i],s[i + 1]);//计算凸包周长 return ans; } int main() { scanf("%d",&n); for(int i = 1;i <= n;++i) { scanf("%lf %lf",&p[i].x,&p[i].y); if(i != 1 && p[i].y < p[1].y) swap(p[i],p[1]);//去重 } double ans = Graham(); printf("%.2f\n",ans); system("pause"); return 0; }