Of course, is to construct a complete package including all the points raised, then is such that there are just two points outside, meet only three cases of this condition.
1. On two consecutive convex hull but not the two points.
2. On two consecutive convex hull but two points.
3. On a convex hull, there is a point in a convex hull of this new point after removing the edge.
Who how quickly taken new convex hull of the point of it is, we can divide the entire convex hull region, each point deleted, may only select a new point in this area. Then we can randomly select a point inside convex hull, I use the convex hull is the center O as the origin of coordinates, then the entire packet to the origin of the projection, before the triangular region in the left and right points is likely to constitute a new point on the edge of the convex hull, then we just need to enumerate the point of violence in the reconstruction of this part of this convex hull edge. Then the first second case through this process, the third case is actually the first case sets the first case, then the new limit male violence handle the first case of wrapping, and then wrapped in a new boss triangle continues to divide, and finally a new reconstructed convex hull sides new convex hull edge.
When the details of sort processing polar angle little pits, attention to the selection range of the angle region of the relative size, large-scale simulation title .... orz
1 // ——By DD_BOND 2 3 //#include<bits/stdc++.h> 4 //#include<unordered_map> 5 //#include<unordered_set> 6 #include<functional> 7 #include<algorithm> 8 #include<iostream> 9 //#include<ext/rope> 10 #include<iomanip> 11 #include<climits> 12 #include<cstring> 13 #include<cstdlib> 14 #include<cstddef> 15 #include<cstdio> 16 #include<memory> 17 #include<vector> 18 #include<cctype> 19 #include<string> 20 #include<cmath> 21 #include<queue> 22 #include<deque> 23 #include<ctime> 24 #include<stack> 25 #include<map> 26 #include<set> 27 28 #define fi first 29 #define se second 30 #define pb push_back 31 #define MP make_pair 32 33 #pragma GCC optimize(3) 34 #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") 35 36 using namespace std; 37 38 typedef long double db; 39 typedef long long ll; 40 typedef pair<db,db> Pd; 41 typedef pair<int,int> P; 42 typedef pair<ll,ll> Pll; 43 44 const db eps=1e-8; 45 const int MAXN=1e6+10; 46 const db pi=acos(-1.0); 47 const ll INF=0x3f3f3f3f3f3f3f3f; 48 49 inline int dcmp(db x){ 50 if(fabs(x)<eps) return 0; 51 return (x>0? 1: -1); 52 } 53 54 inline db Sqrt(db x){ 55 return x>0? sqrt(x): 0; 56 } 57 58 inline db sqr(db x){ return x*x; } 59 60 struct Point{ 61 db x,y,ang; 62 Point(){ x=0,y=0; } 63 Point(db _x,db _y):x(_x),y(_y){} 64 void input(){ 65 double _x,_y; 66 scanf("%lf%lf",&_x,&_y); 67 x=_x,y=_y; 68 } 69 bool operator ==(const Point &b)const{ 70 return (dcmp(x-b.x)==0&&dcmp(y-b.y)==0); 71 } 72 bool operator !=(const Point &b)const{ 73 return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0)); 74 } 75 bool operator <(const Point &b)const{ 76 return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x); 77 } 78 Point operator +(const Point &b)const{ 79 return Point(x+b.x,y+b.y); 80 } 81 Point operator -(const Point &b)const{ 82 return Point(x-b.x,y-b.y); 83 } 84 Point operator *(db a){ 85 return Point(x*a,y*a); 86 } 87 Point operator /(db a){ 88 return Point(x/a,y/a); 89 } 90 DB LEN2 () { // square of the length 91 is return SQR (X) + SQR (Y); 92 } 93 DB len () { // length 94 return Sqrt (LEN2 ()); 95 } 96 DB Polar ( ) { // polar angle vector 97 return of atan2 (Y, x); // return the angle between the positive x-axis (-pi ~ PI] 98 } 99 }; 100 101 inline DB Cross (Point a, Point B) { // cross product 102 return AX-AY * * by BX; 103 } 104 105 inline DB DOT (Point A, Point B) { // dot product 106 return AX + AY * * b.x by; 107 } 108 109 inline DB DIS (Point A, Point B) { // two points from 110 Point P = BA; return p.len (); 111 } 112 113 Point centre_of_polygon (Point * P, int n-) { // polygonal center of gravity weighted average value of the center of gravity request triangular area 114 DB SUM = 0 , SUMX = 0 , Sumy = 0 ; 115 Point P1 = P [ 0 ], P2 = P [ . 1],p3; 116 for(int i=2;i<n;i++){ 117 p3=p[i]; 118 db area=cross(p2-p1,p3-p2)/2; 119 sum+=area; 120 sumx+=(p1.x+p2.x+p3.x)*area; 121 sumy+=(p1.y+p2.y+p3.y)*area; 122 p2=p3; 123 } 124 return Point(sumx/(3*sum),sumy/(3*sum)); 125 } 126 127 Point tmp[MAXN],ins[MAXN]; 128 129 int convex_hull(Point *p,int n,Point *ch){ //求凸包 130 int m=0; 131 sort(p,p+n); 132 for(int i=0;i<n;i++){ 133 while(m>1&&dcmp(cross(tmp[m-1]-tmp[m-2],p[i]-tmp[m-1]))<0) m--; 134 tmp[m++]=p[i]; 135 } 136 int k=m; 137 for(int i=n-2;i>=0;i--){ 138 while(m>k&&dcmp(cross(tmp[m-1]-tmp[m-2],p[i]-tmp[m-1]))<0) m--; 139 tmp[m++]=p[i]; 140 } 141 if(n>1) m--; 142 for(int i=0;i<m;i++) ch[i]=tmp[i]; 143 return m; 144 } 145 146 db ans; 147 pair<db,int>rec[MAXN]; 148 Point point[MAXN],convex[MAXN],o; 149 vector<Point>side[MAXN],in[MAXN],st; 150 151 bool cmp(Point a,Point b){ 152 db dx=(a-o).polar(),dy=(b-o).polar(); 153 if(dcmp(dx-dy)==0) return dis(a,o)>dis(b,o); 154 return dx<dy; 155 } 156 157 int main(void){ 158 int n,m; scanf("%d",&n); 159 for(int i=0;i<n;i++) point[i].input(); 160 161 m=convex_hull(point,n,convex); 162 o=centre_of_polygon(convex,m); 163 164 sort(point,point+n,cmp); 165 sort(convex,convex+m,cmp); 166 167 for(int i=0;i<n;i++){ 168 point[i].ang=(point[i]-o).polar(); 169 point[i+n]=point[i]; 170 point[i+n].ang+=2*pi; 171 } 172 for(int i=0;i<m;i++){ 173 convex[i].ang=(convex[i]-o).polar(); 174 convex[i+m]=convex[i]; 175 convex[i+m].ang+=2*pi; 176 } 177 178 for(int i=0,j=0;i<m;i++){ 179 while(dcmp(convex[i].ang-point[j].ang)>0) j++; 180 while(dcmp(point[j].ang-convex[i+1].ang)<0){ 181 if(point[j]!=convex[i]) side[i].pb(point[j]); 182 j++; 183 } 184 } 185 186 // a point on convex 187 for(int i=0;i<m;i++){ 188 int l=(i==0? m-1: i-1),p=0; 189 tmp[p++]=convex[l]; 190 for(int j=0;j<side[l].size();j++){ 191 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],side[l][j]-tmp[p-1]))<0) p--; 192 tmp[p++]=side[l][j]; 193 } 194 for(int j=0;j<side[i].size();j++){ 195 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],side[i][j]-tmp[p-1]))<0) p--; 196 tmp[p++]=side[i][j]; 197 } 198 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],convex[i+1]-tmp[p-1]))<0) p--; 199 tmp[p++]=convex[i+1]; 200 201 db sum=dis(convex[l],convex[i])+dis(convex[i],convex[i+1]); 202 for(int j=0;j<p-1;j++) sum-=dis(tmp[j],tmp[j+1]); 203 rec[i]=MP(sum,i); 204 } 205 sort(rec,rec+m,greater<pair<db,int> >()); 206 if(abs(rec[0].se-rec[1].se)!=1&&abs(rec[0].se-rec[1].se)!=m-1) ans=max(ans,rec[0].fi+rec[1].fi); 207 if(abs(rec[0].se-rec[2].se)!=1&&abs(rec[0].se-rec[2].se)!=m-1) ans=max(ans,rec[0].fi+rec[2].fi); 208 if(abs(rec[1].se-rec[2].se)!=1&&abs(rec[1].se-rec[2].se)!=m-1) ans=max(ans,rec[1].fi+rec[2].fi); 209 210 // two consecutive point on convex 211 for(int i=0;i<m;i++){ 212 int l=(i==0? m-1: i-1),p=0; 213 tmp[p++]=convex[l]; 214 for(int j=0;j<side[l].size();j++){ 215 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],side[l][j]-tmp[p-1]))<0) p--; 216 tmp[p++]=side[l][j]; 217 } 218 for(int j=0;j<side[i].size();j++){ 219 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],side[i][j]-tmp[p-1]))<0) p--; 220 tmp[p++]=side[i][j]; 221 } 222 for(int j=0;j<side[(i+1)%m].size();j++){ 223 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],side[(i+1)%m][j]-tmp[p-1]))<0) p--; 224 tmp[p++]=side[(i+1)%m][j]; 225 } 226 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],convex[i+2]-tmp[p-1]))<0) p--; 227 tmp[p++]=convex[i+2]; 228 229 db sum=dis(convex[l],convex[i])+dis(convex[i],convex[i+1])+dis(convex[i+1],convex[i+2]); 230 for(int j=0;j<p-1;j++) sum-=dis(tmp[j],tmp[j+1]); 231 ans=max(ans,sum); 232 } 233 234 // a point on convex and a point inside convex 235 for(int i=0;i<m;i++){ 236 int l=(i==0? m-1: i-1),p=0; 237 tmp[p++]=convex[l]; 238 if(i==0) tmp[p-1].ang-=2*pi; 239 for(int j=0;j<side[l].size();j++){ 240 st.pb(side[l][j]); 241 if(i==0) st.back().ang-=2*pi; 242 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],side[l][j]-tmp[p-1]))<0) p--; 243 tmp[p++]=side[l][j]; 244 } 245 for(int j=0;j<side[i].size();j++){ 246 st.pb(side[i][j]); 247 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],side[i][j]-tmp[p-1]))<0) p--; 248 tmp[p++]=side[i][j]; 249 } 250 while(p>1&&dcmp(cross(tmp[p-1]-tmp[p-2],convex[i+1]-tmp[p-1]))<0) p--; 251 tmp[p++]=convex[i+1]; 252 253 for(int j=0,k=0;j<p-1;j++){ 254 while(k<st.size()&&dcmp(tmp[j].ang-st[k].ang)>0) k++; 255 while(k<st.size()&&dcmp(st[k].ang-tmp[j+1].ang)<0){ 256 if(tmp[j]!=st[k]) in[j].pb(st[k]); 257 k++; 258 } 259 } 260 db sum=dis(convex[l],convex[i])+dis(convex[i],convex[i+1]); 261 for(int j=0;j<p-1;j++) sum-=dis(tmp[j],tmp[j+1]); 262 for(int j=1;j<p-1;j++){ 263 int t=0; 264 ins[t++]=tmp[j-1]; 265 for(int k=0;k<in[j-1].size();k++){ 266 while(t>1&&dcmp(cross(ins[t-1]-ins[t-2],in[j-1][k]-ins[t-1]))<0) t--; 267 ins[t++]=in[j-1][k]; 268 } 269 for(int k=0;k<in[j].size();k++){ 270 while(t>1&&dcmp(cross(ins[t-1]-ins[t-2],in[j][k]-ins[t-1]))<0) t--; 271 ins[t++]=in[j][k]; 272 } 273 while(t>1&&dcmp(cross(ins[t-1]-ins[t-2],tmp[j+1]-ins[t-1]))<0) t--; 274 ins[t++]=tmp[j+1]; 275 276 db now=sum+dis(tmp[j-1],tmp[j])+dis(tmp[j],tmp[j+1]); 277 for(int k=0;k<t-1;k++) now-=dis(ins[k],ins[k+1]); 278 ans=max(ans,now); 279 } 280 st.clear(); 281 for(int j=0;j<p;j++) in[j].clear(); 282 } 283 printf("%.12f\n",(double)ans); 284 return 0; 285 }