计算几何练习2

来源:互联网 发布:知乎 扒皮 编辑:程序博客网 时间:2024/06/08 11:27
凸包

【题目描述】:

平面上的N个点,求一个包含所有点的最小的凸多边形,这就是凸包问题了。这可以形象地想成这样:在地上放置一些不可移动的木桩,用一根绳子把他们尽量紧地圈起来,并且为凸边形,这就是凸包了。

【输入描述】:

第一行一个N,表示平面上的点数。

以下N行,每行一个x和y,表示一个点的横坐标和纵坐标。

【输出描述】:

输出最少的点形成的凸多边形,第一个点是y最小的点,如果y相同的点,x小的排在前面。

【样例输入】:

82720 -44346 -2422-2077 -13464520 -4963-1791 1547-1262 4025-2997 913-1667 -2499

【样例输出】:

4520 -49632720 -443-1262 4025-2997 913-1667 -2499

【时间限制、数据范围及描述】:

时间:1s 空间:128M

N<=100000 -10000<=x,y<=10000


凸包可以称得上是计算几何中既难又重要的一个问题了,且应用面非常广。凸包的概念题面中已经描述的比较清晰了,那么该如何做呢?这里介绍的是极角序Graham-Scan算法:

1)qy坐标最小的点p0,若具有最小坐标的点有多个,则取最左边的点作为p0.

2)q中剩余的点按逆时针相对p0的极角排序,若有数个保留其中距p0最远的点得到序列(p1,p2,...pn-1);

3)p0,p1,p2相继入栈

4)for i=3 to n-1 do

      ① while 由次栈顶元素、栈顶元素和Pi所形成角不是向左转do栈顶元素出栈s
      ②pi入栈

5)打印按逆时针排列的栈中的各顶点


AC代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#define ll long longusing namespace std;ll ox,oy;struct node{ll x,y;node(){x=0;y=0;}node(int a,int b){x=a;y=b;}node(const node &p1){x=p1.x;y=p1.y;}node operator = (const node &a){x=a.x;y=a.y;return *this;}};ll operator *(const node & a,const node & b){ll xx1=(a.x-ox)*(b.y-oy),xx2=(a.y-oy)*(b.x-ox);return xx1-xx2;}bool operator <(const node &a,const node &b){ll x;x=a*b;if(x>0)return 1;if(x==0){if((a.x-ox)*(a.x-ox)+(a.y-oy)*(a.y-oy)<(b.x-ox)*(b.x-ox)+(b.y-oy)*(b.y-oy))return 1;}return 0;}bool comp(const node &a,const node &b){if((a.x-ox)*(a.x-ox)+(a.y-oy)*(a.y-oy)<(b.x-ox)*(b.x-ox)+(b.y-oy)*(b.y-oy))return 1;return 0;}node s0[100005];int n,v,k=1;ll miny=2147483647,minx=-2147483647;ll ans[100005];int main(){scanf("%d",&n);for(int i=0;i<n;i++){scanf("%lld%lld",&s0[i].x,&s0[i].y);}for(int i=0;i<n;i++){if(miny>s0[i].y){miny=s0[i].y;minx=s0[i].x;v=i;}if(miny==s0[i].y){if(minx>s0[i].x){minx=s0[i].x;v=i;}}}ox=s0[v].x;oy=s0[v].y;ll temp,xx;temp=s0[0].x;s0[0].x=s0[v].x;s0[v].x=temp;temp=s0[0].y;s0[0].y=s0[v].y;s0[v].y=temp;sort(s0+1,s0+n);ans[0]=0;ans[1]=1;for(int i=2;i<n;i++){ox=s0[ans[k-1]].x;oy=s0[ans[k-1]].y;xx=(s0[ans[k]]*s0[i]);if(xx>0){k++;ans[k]=i;}if(xx==0){if(comp(s0[i],s0[ans[k-1]]));ans[k]=i;}if(xx<0){if(k>2){k--;i--;}elseans[k]=i;}}for(int i=0;i<=k;i++){printf("%lld %lld\n",s0[ans[i]].x,s0[ans[i]].y);}return 0;}
AC截图:


原创粉丝点击