浏览(水了水)网上各种凸包和旋转卡壳的讲解,然后来水这道模板题,结果被坑死了。。。。。。。
我的模板里是double类型的,放到POJ上狂WA(输出用的%.lf,末尾没0啊),于是很愤慨地改成了整型,A了,科学何在啊。
凸包什么的还是比较简单的(吧),想当年学的时候看学堂在线的讲解,想想也是醉人啊,从n^4到n^3到n^2再到nlogn,顺便讲了下规约(reduction),尽管现在我都不知道到底是reduction a to b还是reduction b to a,以及凸包的分治算法。。。。。。然而还是学会了Graham以及Andrew,其实Andrew的维护上凸壳和下凸壳的方法以前在学斜率DP的时候就有些了解了(话说不应该先学凸壳再学斜率DP吗- -+)。
旋转卡壳什么的本来以为很高大上的,结果发现好短,不过嘛,短才体现了算法的巧妙啊。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=50000+5; struct point{ int x,y; }; typedef point vector; bool cmp(point a,point b){ if(a.x!=b.x)return a.x<b.x; return a.y<b.y; } vector operator-(vector a,vector b){ return (vector){a.x-b.x,a.y-b.y}; } int cross(vector a,vector b){ return a.x*b.y-a.y*b.x; } int sqr(int x){return x*x;} int dist(point a,point b){ return sqr(a.x-b.x)+sqr(a.y-b.y); } int cross(point a,point b,point c){ return cross(b-a,c-a); } struct convexhull{ point c[N]; int m; void andrew(point *p,int n){ sort(p+1,p+1+n,cmp); m=0; for(int i=1;i<=n;i++){ while(m>1&&cross(c[m-2],c[m-1],p[i])<=0)m--; c[m++]=p[i]; } int k=m; for(int i=n-1;i>=1;i--){ while(m>k&&cross(c[m-2],c[m-1],p[i])<=0)m--; c[m++]=p[i]; } if(n)m--; } int rotating(){ int j=1; int ans=0; for(int i=0;i<m;i++){ while(cross(c[i],c[i+1],c[j])<cross(c[i],c[i+1],c[j+1])){ j=(j+1)%m; } ans=max(ans,dist(c[i],c[j])); } return ans; } }solver; point a[N]; int main(){ int n;scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y); solver.andrew(a,n); printf("%d",solver.rotating()); return 0; }