Gym 101986D Making Perimeter of the Convex Hull Shortest (polar angle + sort convex hull)

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 }

Guess you like

Origin www.cnblogs.com/dd-bond/p/11622216.html