凸包 andrew模板

来源:互联网 发布:mysql注入语句大全 编辑:程序博客网 时间:2024/05/16 07:23

主要思想

先将所给点以x坐标从小到大(若x相等,以y从小到大)排序,从第一个点开始从左到右扫一遍,用叉积维护下凸壳(上凸壳亦可),在从右到左扫一遍,维护上(下)凸壳即可。
代码如下:
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int n,zz;struct dian{int x,y;} d[100002],tb[100010];bool kp(const dian &a,const dian &b){if(a.x<b.x) return  true;else if(a.x==b.x&&a.y<b.y) return  true;else return false;}int xj(dian &a,dian &b,dian &c)//叉积 {int x1=a.x-c.x, y1=a.y-c.y,    x2=b.x-c.x, y2=b.y-c.y;return x1*y2-x2*y1;}void tubao()//凸包andrew算法{zz=0;for(int i=1;i<=n;i++)   {while(zz>=2&&xj(tb[zz-1],d[i],tb[zz-2])<0) zz--;    tb[zz].x=d[i].x; tb[zz].y=d[i].y; zz++;   }int k=zz;for(int i=n-1;i>=1;i--)   {while(zz>k&&xj(tb[zz-1],d[i],tb[zz-2])<0) zz--;    tb[zz].x=d[i].x; tb[zz].y=d[i].y; zz++;   }if(n>1)zz-=2;//x坐标最小的点会被计算两次且zz比点数大1。 else if(n==1) zz--;for(int i=0;i<=zz;i++) printf("%d %d\n",tb[i].x,tb[i].y);}int main(){scanf("%d",&n);for(int i=1;i<=n;i++)   scanf("%d%d",&d[i].x,&d[i].y);sort(d+1,d+n+1,kp);//预处理tubao();return 0;}


0 0
原创粉丝点击