计算几何之凸包

来源:互联网 发布:网络情缘陈星 编辑:程序博客网 时间:2024/05/13 10:43

这个内容我看了半天,我还是不大清楚,主要靠模板了,更多的知识点击这里,下面是凸包的构造过程:

凸包模板为(我把结构体也写了出来):

struct Point {   double x,y;    friend istream& operator>>(istream &cin,Point &p)    {   cin>>p.x>>p.y;    }    friend ostream& operator<<(ostream &cout,Point &p)    {   cout<<p.x<<" "<<p.y;        return cout;    }    bool operator<(const Point& p) const    {   return y<p.y||(y==p.y&&x<p.x);    } };bool multi(Point p1,Point p2,Point p){   return (p1.x-p.x)*(p2.y-p.y)>(p2.x-p.x)*(p1.y-p.y);}Point P[MAX],res[MAX]; //res保存凸包中的顶点 int Graph(){   int top=1; //返回凸包中点的个数     sort(P,P+n);    if(n==0) return 0; res[0]=P[0];    if(n==1) return 1; res[1]=P[1];    if(n==2) return 2; res[2]=P[2];    for(int i=2;i<n;i++)    {   while(top && multi(P[i],res[top],res[top-1])) top--;        res[++top]=P[i];    }      int len=top;    res[++top]=P[n-2];    for(int i=n-3;i>=0;i--)    {   while(top!=len && multi(P[i],res[top],res[top-1])) top--;        res[++top]=P[i];    }    return top;}

凸包的题目用这个模板一般可以过,但是一般不会单纯的考凸包,会结合旋转卡壳的知识来出题,这里包涵了大多数旋转卡壳的知识。

题1:Tyvj 1150(绳子围点),先用凸包求出最大面积,然后利用Pick定理求出点即可。注意精度问题,统一用__int64型的就行。

#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const int MAX=200010;struct Point{   __int64 x,y;    bool operator<(const Point &P) const    {   return y<P.y||(y==P.y&&x<P.x);    } };Point P[MAX],res[MAX];__int64 Gcd(__int64 n,__int64 m){   return m==0?n:Gcd(m,n%m);}__int64 multi(Point P0,Point P1,Point P2){   return (P1.x-P0.x)*(P2.y-P0.y)>(P2.x-P0.x)*(P1.y-P0.y);} __int64 Graph(__int64 n)  {   __int64 top=1;       sort(P,P+n);      if(n==0) return 0; res[0]=P[0];      if(n==1) return 1; res[1]=P[1];      if(n==2) return 2; res[2]=P[2];      for(int i=2;i<n;i++)      {   while(top && multi(P[i],res[top],res[top-1])) top--;          res[++top]=P[i];      }        __int64 len=top;      res[++top]=P[n-2];      for(int i=n-3;i>=0;i--)      {   while(top!=len && multi(P[i],res[top],res[top-1])) top--;          res[++top]=P[i];      }      return top;  }  __int64 Area(__int64 n)   {   __int64 area=0;      for(int i=1;i<=n;i++)          area+=res[i-1].x*res[i%n].y-res[i%n].x*res[i-1].y;    return area>0?area:-area;       }  __int64 Count(__int64 n)    {   __int64 sum=0;      for(int i=1;i<=n;i++)      {   int dx=abs(res[i%n].x-res[i-1].x);          int dy=abs(res[i%n].y-res[i-1].y);           sum+=Gcd(dx,dy);          }      return sum;      } int main(){   int n;    scanf("%d",&n);    for(int i=0;i<n;i++)        scanf("%I64d%I64d",&P[i].x,&P[i].y);      __int64 len=Graph(n);        __int64 I=(Area(len)-Count(len))/2+1;    printf("%I64d\n",I+Count(len));         return 0;}