• 【kuangbin专题】计算几何_凸包


    1.poj1113 Wall

    题目:http://poj.org/problem?id=1113

    题意:用一条线把若干个点包起来,并且线距离任何一个点的距离都不小于r。求这条线的最小距离是多少?

    分析:这道题的答案是凸包周长加上一个圆周长,即包围凸包的一个圆角多边形,但是没弄明白那些圆角加起来为什么恰好是一个圆。每个圆角是以凸包对应的顶点为圆心,给定的L为半径,与相邻两条边的切点之间的一段圆弧。每个圆弧的两条半径夹角与对应的凸包的内角互补。假设凸包有n条边,则所有圆弧角之和为180°*n-180°*(n-2)=360°。故,围墙周长为=n条平行于凸包的线段+n条圆弧的长度=凸包周长+围墙离城堡距离L为半径的圆周长。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cmath>
      5 using namespace std;
      6 const int maxn=1010;
      7 const double eps=1e-8;
      8 const double pi=acos(-1.0);
      9 inline double sqr(double x){return x*x;}
     10 int sgn(double x){
     11     if (fabs(x)<eps) return 0;
     12     if (x<0) return -1;
     13     return 1;
     14 } 
     15 struct point{
     16     double x,y;
     17     point(){}
     18     point(double _x,double _y):x(_x),y(_y){}
     19     //判断两点相同 
     20     bool operator ==(const point &b) const{  
     21         return sgn(x-b.x)==0 && sgn(y-b.y)==0;
     22     }
     23     // 
     24     point operator -(const point &b) const{
     25         return point(x-b.x,y-b.y);
     26     } 
     27     //叉积 
     28     double operator ^(const point &b) const{
     29         return x*b.y-y*b.x; 
     30     }
     31     //点积
     32     double operator *(const point &b) const{
     33         return x*b.x+y*b.y;
     34     } 
     35     //重载小于号   (求最左下角的点
     36     bool operator <(const point &b)const{
     37         return sgn(x-b.x)==0 ? sgn(y-b.y)<0 : x<b.x;
     38     } 
     39 };
     40 struct line{
     41     point s,e;
     42     line(){}
     43     line(point _s,point _e):s(_s),e(_e){}
     44 };
     45 double dis(point a,point b){
     46     return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
     47 }
     48 struct polygon{
     49     int n;
     50     point p[maxn];
     51     line l[maxn];
     52     void add(point q){
     53         p[n++]=q;
     54     }
     55     void getline(){
     56         for (int i=0;i<n;i++)
     57             l[i]=line(p[i],p[(i+1)%n]);
     58     }
     59     struct cmp{
     60         point p;
     61         cmp(const point &p0):p(p0){}
     62         bool operator ()(const point &aa,const point &bb){
     63             point a=aa,b=bb;
     64             int d=sgn((a-p)^(b-p));
     65             if (d==0){
     66                 return sgn(dis(a,p)-dis(b,p))<0;
     67             }
     68             return d>0;
     69         }
     70     };
     71     //极角排序  先找到左下角的点 
     72     //重载好point的'<' 
     73     void norm(){
     74         point mi=p[0];
     75         for (int i=1;i<n;i++) mi=min(mi,p[i]);
     76         sort(p,p+n,cmp(mi));
     77     } 
     78     //得到凸包,点编号为0--n-1
     79     void Graham(polygon &convex){
     80         norm();
     81         int &top=convex.n;
     82         top=0;
     83         if (n==1){
     84             top=1; convex.p[0]=p[0]; return ;
     85         }
     86         if (n==2){
     87             top=2; convex.p[0]=p[0]; convex.p[1]=p[1];
     88             if (convex.p[0]==convex.p[1]) top--;
     89             return ;
     90         }
     91         convex.p[0]=p[0]; convex.p[1]=p[1]; top=2;
     92         for (int i=2;i<n;i++){
     93             while (top>1 && sgn((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))<=0) top--;
     94             convex.p[top++]=p[i];
     95         }
     96         if (convex.n==2 && (convex.p[0]==convex.p[1])) convex.n--;
     97     } 
     98 };
     99 polygon C;
    100 int main(){
    101     int n,L; cin >> n >> L;
    102     double x,y;
    103     for (int i=0;i<n;i++){
    104         cin >> x >> y;
    105         C.add(point(x,y));
    106     }
    107     polygon ans;
    108     C.Graham(ans);
    109     ans.getline();
    110     double res=0;
    111     for (int i=0;i<ans.n;i++) res+=dis(ans.l[i].s,ans.l[i].e);
    112     res+=2*pi*L;
    113     printf("%d
    ",(int)(res+0.5));
    114     return 0;
    115 }
    poj1113

    (为了套板子,写的很繁琐)

    2.poj2007 Scrambled Polygon

    题目:http://poj.org/problem?id=2007

    题意:求一个凸多边形的凸包。要求起始点为输入的第一个点。

    分析:rt。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 using namespace std;
     6 const double eps=1e-8;
     7 const int maxn=55;
     8 inline double sqr(int x){return x*x*1.0;}
     9 int sgn(double x){
    10     if (fabs(x)<eps) return 0;
    11     if (x<0) return -1;
    12     return 1;
    13 }
    14 struct point{
    15     int x,y;
    16     point(){}
    17     point(int _x,int _y):x(_x),y(_y){}
    18     bool operator ==(const point &b)const{
    19         return (x==b.x && y==b.y);
    20     }
    21     point operator -(const point &b)const{
    22         return point(x-b.x,y-b.y);
    23     }
    24     int operator ^(const point &b)const{
    25         return x*b.y-y*b.x;
    26     }
    27     int operator *(const point &b)const{
    28         return x*b.x+y*b.y;
    29     }
    30     //重载小于号   (求最左下角的点
    31     bool operator <(const point &b)const{
    32         return sgn((x-b.x)*1.0)==0 ? sgn((y-b.y)*1.0)<0 : x<b.x;
    33     } 
    34 }; 
    35 double dis(point a,point b){
    36     return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
    37 }
    38 struct polygon{
    39     int n;
    40     point p[maxn];
    41     void add(point q){
    42         p[n++]=q;
    43     }
    44     struct cmp{
    45         point p;
    46         cmp(const point &p0):p(p0){}
    47         bool operator ()(const point &aa,const point &bb){
    48             point a=aa,b=bb;
    49             int k=(a-p)^(b-p);int d;
    50             if (k==0) d=0;else if (k<0) d=-1; else d=1;
    51             if (d==0){
    52                 return sgn(dis(a,p)-dis(b,p))<0;
    53             }
    54             return d>0;
    55         }
    56     };
    57     //极角排序  先找到左下角的点 
    58     //重载好point的'<' 
    59     void norm(){
    60         point mi=p[0];
    61         for (int i=1;i<n;i++) mi=min(mi,p[i]);
    62         sort(p,p+n,cmp(mi));
    63     } 
    64     //得到凸包,点编号为0--n-1
    65     void Graham(polygon &convex){
    66         norm();
    67         int &top=convex.n;
    68         top=0;
    69         if (n==1){
    70             top=1; convex.p[0]=p[0]; return ;
    71         }
    72         if (n==2){
    73             top=2; convex.p[0]=p[0]; convex.p[1]=p[1];
    74             if (convex.p[0]==convex.p[1]) top--;
    75             return ;
    76         }
    77         convex.p[0]=p[0]; convex.p[1]=p[1]; top=2;
    78         for (int i=2;i<n;i++){
    79             while (top>1 && sgn(((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))*1.0)<=0) top--;
    80             convex.p[top++]=p[i];
    81         }
    82         if (convex.n==2 && (convex.p[0]==convex.p[1])) convex.n--;
    83     } 
    84 };
    85 polygon C;
    86 int main(){
    87     int x,y; point p;
    88     C.n=0; 
    89     cin >> x >> y; p=point(x,y); C.add(p);
    90     while (cin >> x >> y) C.add(point(x,y));
    91     polygon ans;
    92     C.Graham(ans); int k;
    93     for (int i=0;i<ans.n;i++) if (ans.p[i]==p){k=i;break;}
    94     for (int i=0;i<ans.n;i++){
    95         printf("(%d,%d)
    ",ans.p[(k+i)%ans.n].x,ans.p[(k+i)%ans.n].y);
    96     }
    97     return 0;
    98 }
    poj2007

    3.poj1228

      题目:http://poj.org/problem?id=1228

    题意:输入一个凸包上的点(没有凸包内部的点,要么是凸包顶点,要么是凸包边上的点),判断这个凸包是否稳定。所谓稳定就是判断能不能在原有凸包上加点。

    分析:问凸包是否稳定。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 const double eps=1e-8;
     7 const int maxn=1010;
     8 int sgn(double x){
     9     if (fabs(x)<eps) return 0;
    10     if (x<0) return -1;
    11     return 1;
    12 }
    13 struct point{
    14     double x,y;
    15     point(){}
    16     point(double _x,double _y):x(_x),y(_y){}
    17     point operator -(const point &b)const{
    18         return point(x-b.x,y-b.y);
    19     }
    20     double operator ^(const point &b)const{
    21         return x*b.y-y*b.x;
    22     }
    23 }p[maxn],pp[maxn]; 
    24 bool cmp(point a,point b) {return a.x < b.x || (a.x == b.x && a.y < b.y);}
    25 int convexhull(point p[],int n,point pp[]){
    26     sort(p,p+n,cmp);
    27     int m=0;
    28     for (int i=0;i<n;i++){
    29         while (m>1 && ((pp[m-1]-pp[m-2])^(p[i]-pp[m-2]))<0) m--;
    30         pp[m++]=p[i];
    31     } 
    32     int k=m;
    33     for (int i=n-2;i>=0;i--){
    34         while (m>k && ((pp[m-1]-pp[m-2])^(p[i]-pp[m-2]))<0) m--;
    35         pp[m++]=p[i];
    36     }
    37     return m-1;
    38 }
    39 bool check(point p[],int n){
    40     for (int i=1;i<n-2;i++){
    41         if (((p[i-1]-p[i])^(p[i+1]-p[i]))!=0 &&
    42             ((p[i]-p[i+1])^(p[i+2]-p[i+1]))!=0) return false;  //保证至少有三个点在同一条边上 
    43     } 
    44     return true;
    45 }
    46 int main(){
    47     int t,n; double x,y; cin >> t;
    48     while (t--){
    49         cin >> n;
    50         for (int i=0;i<n;i++) cin >> p[i].x >> p[i].y;
    51         if (n<6){cout << "NO
    ";continue;}
    52         int cnt=convexhull(p,n,pp);
    53         if (check(pp,cnt)) cout << "YES
    "; else cout << "NO
    ";
    54     }
    55     return 0;
    56 }
    poj1228

    4

    5.poj3348 Cows

    题目:http://poj.org/problem?id=3348

    题意:给出一些点圈出一个最大面积每50平方养一头牛问最多能养多少牛。

    分析:凸包+多边形面积。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<cmath>
      5 using namespace std;
      6 const int maxn=10005;
      7 inline int sqr(int x){return x*x;}
      8 struct point{
      9     int x,y;
     10     point(){}
     11     point(int _x,int _y):x(_x),y(_y){}
     12     //判断两点相同 
     13     bool operator ==(const point &b) const{  
     14         return x-b.x==0 && y-b.y==0;
     15     }
     16     // 
     17     point operator -(const point &b) const{
     18         return point(x-b.x,y-b.y);
     19     } 
     20     //叉积 
     21     int operator ^(const point &b) const{
     22         return x*b.y-y*b.x; 
     23     }
     24     //点积
     25     int operator *(const point &b) const{
     26         return x*b.x+y*b.y;
     27     } 
     28     //重载小于号   (求最左下角的点
     29     bool operator <(const point &b)const{
     30         return x-b.x==0?y-b.y<0:x<b.x;
     31     } 
     32 };
     33 struct line{
     34     point s,e;
     35     line(){}
     36     line(point _s,point _e):s(_s),e(_e){}
     37 };
     38 int dis(point a,point b){
     39     return (int)sqrt(1.0*sqr(a.x-b.x)+1.0*sqr(a.y-b.y));
     40 }
     41 struct polygon{
     42     int n;
     43     point p[maxn];
     44     void add(point q){p[n++]=q;}
     45     struct cmp{
     46         point p;
     47         cmp(const point &p0):p(p0){}
     48         bool operator ()(const point &aa,const point &bb){
     49             point a=aa,b=bb;
     50             int k=(a-p)^(b-p);
     51             if (k==0){
     52                 return dis(a,p)-dis(b,p)<0;
     53             }
     54             return k>0;
     55         }
     56     };
     57     //极角排序  先找到左下角的点 
     58     //重载好point的'<' 
     59     void norm(){
     60         point mi=p[0];
     61         for (int i=1;i<n;i++) mi=min(mi,p[i]);
     62         sort(p,p+n,cmp(mi));
     63     } 
     64     //得到凸包,点编号为0--n-1
     65     void Graham(polygon &convex){
     66         norm();
     67         int &top=convex.n;
     68         top=0;
     69         if (n==1){
     70             top=1; convex.p[0]=p[0]; return ;
     71         }
     72         if (n==2){
     73             top=2; convex.p[0]=p[0]; convex.p[1]=p[1];
     74             if (convex.p[0]==convex.p[1]) top--;
     75             return ;
     76         }
     77         convex.p[0]=p[0]; convex.p[1]=p[1]; top=2;
     78         for (int i=2;i<n;i++){
     79             while (top>1 && ((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))<=0) top--;
     80             convex.p[top++]=p[i];
     81         }
     82         if (convex.n==2 && (convex.p[0]==convex.p[1])) convex.n--;
     83     } 
     84     int getarea(){
     85         int sum=0;
     86         for (int i=0;i<n;i++) sum+=(p[i]^(p[(i+1)%n]));
     87         return sum/2;
     88     }
     89 };
     90 polygon C;
     91 int main(){
     92     int n,x,y; cin >> n; C.n=0;
     93     for (int i=0;i<n;i++){
     94         cin >> x >> y;
     95         C.add(point(x,y));
     96     }
     97     polygon ans; C.Graham(ans);
     98     cout << ans.getarea()/50 << endl;
     99     return 0;
    100 }
    poj3348

     6.poj1259/hdoj6219

    题意:给出n个点,求出最大面积的凸包且凸包内不包含原点集中的点。

    分析:rt。求最大面积空凸包。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 const double eps=1e-8;
     7 const int maxn=1005; 
     8 inline double sqr(double x){return x*x;}
     9 int sgn(double x){
    10     if (fabs(x)<eps) return 0;
    11     if (x<0) return -1;
    12     return 1;
    13 } 
    14 struct point{
    15     double x,y;
    16     point(){}
    17     point(double _x,double _y):x(_x),y(_y){}
    18     //判断两点相同 
    19     bool operator ==(const point &b) const{  
    20         return sgn(x-b.x)==0 && sgn(y-b.y)==0;
    21     }
    22     // 
    23     point operator -(const point &b) const{
    24         return point(x-b.x,y-b.y);
    25     } 
    26     //叉积 
    27     double operator ^(const point &b) const{
    28         return x*b.y-y*b.x; 
    29     }
    30     //点积
    31     double operator *(const point &b) const{
    32         return x*b.x+y*b.y;
    33     } 
    34     //重载小于号   (求最左下角的点
    35     bool operator <(const point &b)const{
    36         return sgn(x-b.x)==0 ? sgn(y-b.y)<0 : x<b.x;
    37     } 
    38 }p[maxn],pp[maxn];
    39 point tmp;
    40 double dp[maxn][maxn];
    41 double empty_convex(point p[],int n,point o){
    42     double ans=0;
    43     for (int i=0;i<n;i++) for (int j=0;j<n;j++) dp[i][j]=0;
    44     for (int i=0;i<n;i++){
    45         int j=i-1;
    46         while (j>=0 && ((p[i]-o)^(p[j]-o))==0) j--;
    47         bool flag=(j==i-1);
    48         while (j>=0){
    49             int k=j-1;
    50             while (k>=0 && ((p[i]-p[k])^(p[j]-p[k]))>0) k--;
    51             double area=fabs((p[i]-o)^(p[j]-o))/2.0;
    52             if (k>=0) area+=dp[j][k];
    53             if (flag) dp[i][j]=area;
    54             ans=max(ans,area);
    55             j=k;
    56         }
    57         if (flag){
    58             for (int j=1;j<i;j++) dp[i][j]=max(dp[i][j],dp[i][j-1]);
    59         }
    60     }
    61     return ans;
    62 }
    63 double dist(point a,point b){
    64     return sqrt((a-b)*(a-b));
    65 }
    66 bool cmp_angle(point a,point b){
    67     double res=(a-tmp)^(b-tmp);
    68     if (res) return res>0;
    69     return dist(a,tmp)<dist(b,tmp);
    70 }
    71 double largest_empty_convex(point p[],int n){
    72     double ans=0;
    73     for (int i=0;i<n;i++){
    74         tmp=p[i];
    75         int cnt=0;
    76         for (int j=0;j<n;j++){
    77             if (p[j].y>tmp.y || p[j].y==tmp.y && p[j].x>tmp.x) pp[cnt++]=p[j];
    78         }
    79         sort(pp,pp+cnt,cmp_angle);  //根据极角排序
    80         ans=max(ans,empty_convex(pp,cnt,tmp)); 
    81     }
    82     return ans;
    83 }
    84 int main(){
    85     int t,n; cin >> t;
    86     while (t--){
    87         cin >> n;
    88         for (int i=0;i<n;i++) cin >> p[i].x >> p[i].y;
    89         double ans=largest_empty_convex(p,n);
    90         printf("%.1f
    ",ans);
    91     }
    92     return 0;
    93 } 
    poj1259
  • 相关阅读:
    JMeter设置中文界面显示
    Linux搭建JAVA环境
    SQLyog连接MySQL时出现错误代号:2058
    SQL基础教程(第2版)笔记整理
    sqlserver查询数据的所有表名和行数
    【ASP.NET 问题】IIS发布网站后出现 "处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误"的解决办法
    Asp.net在IE10、IE11下事件丢失经验总结
    SQL 2008 R2下载 升级R2 SP1或者SQL 2008从10.50.1600升级10.5.2500
    IE9浏览器中的My97日历控件刷新后无法打开问题解决办法
    windows2008 c盘清理
  • 原文地址:https://www.cnblogs.com/changer-qyz/p/9770115.html
Copyright © 2020-2023  润新知