POJ 1228 Grandpa's Estate (求稳定凸包)

来源:互联网 发布:福州橙子网络 编辑:程序博客网 时间:2024/06/05 16:47

一个凸包丢了一些点,剩下的点能否表示原凸包?

先看一下什么情况下可以表示原凸包:现有的凸包每边都有3个以上的点。这样丢掉的点必定也在凸包上,否则现有的点不再凸包上,与已知不符。

做法就是根据所给点再算一次凸包,判断每边是否有三个以上的点。

注意,n<6为NO,所给点为直线为NO。

常用的凸包模版有时会包含边上的点(比如起始三点共线),有的时候不会。借此机会整理下自己的凸包哈!

//Memory: 260K//Time: 0MS#include <iostream>#include <algorithm>#include <math.h>using namespace std;int top;struct POINT{double x,y;};POINT p[1005],ch[1005];double dist(POINT a,POINT b){return sqrt( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) );}double multiply(POINT sp,POINT ep,POINT op){return (sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y);}bool online(POINT s,POINT e,POINT p) {return( (multiply(e,p,s)==0) && ( ( (p.x-s.x)*(p.x-e.x)<=0 ) && ( (p.y-s.y)*(p.y-e.y)<=0 ) ) ); }bool ptcmp(POINT a,POINT b){if(multiply(a,b,p[0])>0 || (multiply(a,b,p[0])==0 && (dist(a,p[0])<dist(b,p[0]))))return 1;return 0;}void graham(int n){int i,k=0;top=1;POINT temp;for(i=1;i<n;i++)if(p[i].y<p[k].y || (p[i].y==p[k].y && p[i].x<p[k].x))k=i;temp=p[0];p[0]=p[k];p[k]=temp;sort(p+1,p+n,ptcmp);ch[0]=p[0];ch[1]=p[1];for(i=2;i<n;i++){while(top>=1 && multiply(p[i],ch[top],ch[top-1])>=0)top--;ch[++top]=p[i];}ch[++top]=p[0];}int main(){int cas,n;cin>>cas;while(cas--){cin>>n;int i,j,flag=0,k=0;for(i=0;i<n;i++)cin>>p[i].x>>p[i].y;graham(n);for(i=1;i<top-1;i++){flag=0;for(j=0;j<=n;j++){if(online(ch[i],ch[i-1],p[j]))flag++;if(flag>=3)break;}if(flag<3)k=1;}if(n<=5)k=1;else{for(i=2;i<n;i++)if(multiply(p[i-2],p[i-1],p[i])!=0)break;if(n==i)k=1;}if(k!=1)cout<<"YES"<<endl;elsecout<<"NO"<<endl;}return 0;}


原创粉丝点击