#include<bits/stdc++.h> usingnamespace std; structpoint { double x,y; point():x(0),y(0) {} point(double x,double y):x(x),y(y) {} }; #define eps 1e-8 intsgn(double x) { if(fabs(x)<0)return0; return x<0?-1:1; } doublecro(point a,point b) { return a.x*b.y-a.y*b.x; } point operator-(point a,point b) { returnpoint(a.x-b.x,a.y-b.y); } voidAndrewConvex(point* num,point* ans,int n,int&m) { m=0; for(int i=0;i<n;i++) { while(m>1&&sgn(cro(ans[m-1]-ans[m-2],num[i]-ans[m-1]))<0)m--; ans[m++]=num[i]; } int j=m; for(int i=n-2;i>=0;i--) { while(m>j&&sgn(cro(ans[m-1]-ans[m-2],num[i]-ans[m-1]))<0)m--; ans[m++]=num[i]; } if(n>1)m--; } doublelength(point a,point b) { returnsqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } booloperator<(const point a,const point b) { return a.x<b.x||(fabs(a.x-b.x)<eps&&a.y<b.y); } constint N=1e6+1; point p1[N],p2[N];
intmain() { int n; cin>>n; for(int i=0;i<n;i++)cin>>p1[i].x>>p1[i].y; int m=0; sort(p1,p1+n); AndrewConvex(p1,p2,n,m); double ans=0; for(int i=0;i<m;i++)ans+=length(p2[i],p2[(i+1)%m]); printf("%.2lf",ans); }
旋转卡壳
用于求凸包直径,即多边形的两点距离最大值。
注意得先求凸包,再求旋转卡壳。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
doubletrangleSquare(point a, point b, point c) { // 三角形面积的2倍,其实应该就是平行四边形 returnfabs(cro(b - a, c - a)); } doubleConvexDiameter(point* p, int n) { if (n == 2)returnlength(p[0]-p[1]); int cur = 0; double ans = 0.0; for (int i = 0; i < n; i++) { while (trangleSquare(p[i], p[(i + 1) % n], p[cur]) <= trangleSquare(p[i], p[(i + 1) % n], p[(cur + 1) % n])) cur = (cur + 1) % n; ans = max(ans, max(length(p[i]-p[cur]), length(p[i + 1]-p[cur]))); } return ans; }
#include<bits/stdc++.h> usingnamespace std; structpoint { double x,y; point():x(0),y(0) {} point(double x,double y):x(x),y(y) {} }; #define eps 1e-8 intsgn(double x) { if(fabs(x)<0)return0; return x<0?-1:1; } doublecro(point a,point b) { return a.x*b.y-a.y*b.x; } point operator-(point a,point b) { returnpoint(a.x-b.x,a.y-b.y); } voidAndrewConvex(point* num,point* ans,int n,int&m) { m=0; for(int i=0;i<n;i++) { while(m>1&&sgn(cro(ans[m-1]-ans[m-2],num[i]-ans[m-1]))<0)m--; ans[m++]=num[i]; } int j=m; for(int i=n-2;i>=0;i--) { while(m>j&&sgn(cro(ans[m-1]-ans[m-2],num[i]-ans[m-1]))<0)m--; ans[m++]=num[i]; } if(n>1)m--; } doublelength(point a) { returnsqrt((a.x*a.x)+(a.y*a.y)); } booloperator<(const point a,const point b) { return a.x<b.x||(fabs(a.x-b.x)<eps&&a.y<b.y); } constint N=1e6+5; point A[N], B[N], C[N]; doubletrangleSquare(point a, point b, point c) { returnfabs(cro(b - a, c - a)); } doubleConvexDiameter(point* p, int n) { if (n == 2)returnlength(p[0]-p[1]); int cur = 0; double ans = 0.0; for (int i = 0; i < n; i++) { //while (Line2Point(p[i], p[(i + 1) % n], p[cur]) <= Line2Point(p[i], p[(i + 1) % n], p[(cur + 1) % n])) while (trangleSquare(p[i], p[(i + 1) % n], p[cur]) <= trangleSquare(p[i], p[(i + 1) % n], p[(cur + 1) % n])) cur = (cur + 1) % n; ans = max(ans, max(length(p[i]-p[cur]), length(p[i + 1]-p[cur]))); } return ans; } istream& operator>>(istream& in, point& p) { in >> p.x >> p.y; return in; }
voidsolve() { #define pi 3.1415926535897932384626433 int n; cin >> n; for (int i = 0; i < n; i++)cin >> A[i]; double ans = 0; for (int i = 0; i < n; i++)ans += length(A[i]-A[(i + 1) % n]); int m; cin >> m; for (int i = 0; i < m; i++)cin >> B[i]; int k = 0; sort(B, B + m); AndrewConvex(B, C, m, k); ans += 2 * pi * ConvexDiameter(C, k); printf("%.15lf\n", ans); }
intmain() { ios::sync_with_stdio(false); cin.tie(0); int t = 1; cin>>t; while (t--)solve(); cout.flush(); return0; }