这个内容我看了半天,我还是不大清楚,主要靠模板了,更多的知识点击这里,下面是凸包的构造过程:
凸包模板为(我把结构体也写了出来):
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;
}