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