• Gym 101986D Making Perimeter of the Convex Hull Shortest(凸包+极角排序)


    首先肯定是构造一个完整的凸包包括所有的点,那么要使得刚好有两个点在外面,满足这个条件的只有三种情况。

    1.两个在凸包上但是不连续的两个点。

    2.两个在凸包上但是连续的两个点。

    3.一个在凸包上,还有一个在这个点去掉后这段新凸包边上的一个点。

    如何快速的截取新凸包的点是谁呢,我们可以将整个凸包划分区域,每个点删掉后,只可能在这块区域内选择新的点。那么我们就可以随机在凸包内部选择一个点,我使用的是凸包的重心作为坐标原点o,那么整个凸包移到原点处,然后在这个点的左侧和右侧的三角形区域内才是有可能构成新凸包边上的点,那我们只需要暴力枚举这部分内的点重构这条凸包边。那么第一第二种情况可以通过这个处理,第三种情况其实就是第一种情况套了第一种情况,那么就限暴力处理第一种情况的新凸包边,再在新凸包上继续分割三角区域,最后重构新凸包边中的新凸包边。

    极角排序的时候细节处理有点坑,注意选择区域范围的角度相对大小,大型模拟题.... or

    k点为重心

      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(){  //长度平方
     91         return sqr(x)+sqr(y);
     92     }
     93     db len(){   //长度
     94         return Sqrt(len2());
     95     }
     96     db polar(){ //向量的极角
     97         return atan2(y,x);   //返回与x轴正向夹角(-pi~pi]
     98     }
     99 };
    100 
    101 inline db cross(Point a,Point b){   //叉积
    102     return a.x*b.y-a.y*b.x;
    103 }
    104 
    105 inline db dot(Point a,Point b){ //点积
    106     return a.x*b.x+a.y*b.y;
    107 }
    108 
    109 inline db dis(Point a,Point b){ //两点的距离
    110     Point p=b-a;    return p.len();
    111 }
    112 
    113 Point centre_of_polygon(Point *p,int n){    //三角形重心加面积权值的平均求多边形的重心
    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
    ",(double)ans);
    284     return 0;
    285 }
  • 相关阅读:
    Swift新手教程3-字符串String
    BZOJ 2006 NOI2010 超级钢琴 划分树+堆
    Makefile学习(一)[第二版]
    leetcode 26 -- Remove Duplicates from Sorted Array
    谈谈我眼中的泛型
    oracle表空间查询维护命令大全之三(暂时表空间)史上最全
    超大表盘手表 : 超大表盘手表图片及搭配,超大表盘手表价格-美丽说
    Linux下安装Python3.3.0
    朝阳公园朝阳公园水下猎人潜水艇团购:水下猎人潜艇观光+水下梭镖打鱼套票!体验前所未有的水下休闲娱乐,探寻海底世界-聚齐北京团购
    隐形选购指南_亿超眼镜网
  • 原文地址:https://www.cnblogs.com/dd-bond/p/11622216.html
Copyright © 2020-2023  润新知