Poj 1228 Grandpa's Estate (凸包及唯一性判定)

来源:互联网 发布:js广告代码生成器 编辑:程序博客网 时间:2024/06/15 21:50

题目链接: http://poj.org/problem?id=1228

题意:grandfather给Kamran一块凸包的土地,有钉子钉在凸包的边上,现在其中一些钉子掉掉了,判断K是否能根据剩下的钉子判断出原来这边凸包的土地,能输出YES  不能输出NO.

思路:Graham水平序求凸包,用叉积判断每一边上是否还有其他的点。因为如果一条边上只有两个点,是可以向外添加一个点改变凸包形状,而三点就固定了这条边。特殊地,如果所有点共线,输出NO。


题目没看懂……网上的各路解题报告更加看不懂……还是自己想比较靠谱。

今天帮助了一下旁边的新人(虽然我也是新人……),发现刚进ACM实验室的时候自己写的代码好水……

这题Poj测试数据很弱(貌似没有全部共线的数据?)。

#include <cstdio>#include <iostream>#include <cmath>#include <algorithm>using namespace std;const int NUM=50004;int n,len;struct Point{    int x,y;void get (){scanf("%d%d",&x,&y);    }    bool operator < (const Point& _P) const    {        return y<_P.y||(y==_P.y&&x<_P.x);    };}pt[NUM],ch[NUM];  int cross (Point p,Point q,Point x){return (p.x-x.x)*(q.y-x.y)-(q.x-x.x)*(p.y-x.y);  }//ch[0]~ch[len-1]保存凸包,保存顶点与边上的点void Graham (Point pt[],Point ch[],int &len,int n){int i,top=1;    sort(pt,pt+n);    ch[0]=pt[0];    ch[1]=pt[1];    for (i=2;i<n;i++)    {        while (top>0 && cross(ch[top],pt[i],ch[top-1]) < 0)   //边上的点将被存入ch[]数组            top--;        ch[++top]=pt[i];    }    int temp=top;    for (i=n-2;i>=0;i--)    {        while (top>temp && cross(ch[top],pt[i],ch[top-1]) < 0)            top--;        ch[++top]=pt[i];    }    len=top;    }bool Judge (Point pt[],int &len){bool flag=true,Online=true; //flag表示是否有可能共线for (int i=0;i<len;i++)if (cross(ch[(i+1)%len],ch[(len+i-1)%len],ch[i]) == 0)   //如果该点与左右两边的点共线Online=true;else if (Online == false)   //该点为拐点且之前的边上没有共线点return false;else                //该点为拐点Online=false,flag=false;if (flag)return false;return true;}int main (){int T;scanf("%d",&T);while (T--){scanf("%d",&n);for (int i=0;i<n;i++)pt[i].get();if (n<=5){printf("NO\n");continue;}Graham (pt,ch,len,n);if (Judge(ch,len))printf("YES\n");elseprintf("NO\n");}return 0;}/*380 00 10 21 22 22 12 01 090 01 02 02 12 20 20 11 30 460 10 20 30 40 50 6YESYesNO*/


原创粉丝点击