poj 1228 凸包

题意:给出一个去掉几个点后的凸包,判断是不是原始凸包。

看了大牛的思想后才知道:只要判断凸包的每个边上有三个顶点,就可以判断该凸包为原始凸包。

1、少于六个点不可能是原始凸包。

2、利用graham算法找出形成该凸包至少需要的顶点,存进数组res[]中,剩余的存进leave[]数组中。

3、遍历两个数组判断是否满足条件。

#include<iostream>

#include<cstdio>

using namespace std;

#define MAX_INT 123456789

struct point

{

	int x,y;

};

point vertex[1000];

int res[1000],leave[1000],len;

int angle(point p0,point p1,point p2)//p1,p2相对于p0的极角大小

{

    return (p1.y-p0.y)*(p2.x-p0.x)-(p2.y-p0.y)*(p1.x-p0.x);

}

int judge(point p0,point p1,point p2)

{

	return (p2.y-p0.y)*(p1.x-p0.x)>(p1.y-p0.y)*(p2.x-p0.x);

}

int dist(point p1,point p2)

{

	return (p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y);

}

int cmp(const void* a,const void *b)

{

	int k;

	point p1,p2;

	p1=*(point*)a; p2=*(point*)b;

	k=angle(vertex[0],p1,p2);

	if(k==0)

		return dist(vertex[0],p1)>dist(vertex[0],p2);

	return k>0;

}

int graham(int m)

{

	int i,top=0;

	res[0]=0; res[1]=1; len=0;

	qsort(vertex+1,m-1,sizeof(vertex[0]),cmp);

	vertex[m++]=vertex[0];

	for(top=1,i=2;i<m;i++)

	{

		while(top && !judge(vertex[res[top-1]],vertex[res[top]],vertex[i]))//去掉不合适的点何在同一条直线上的点

			leave[len++]=res[top--];

		res[++top]=i;

	}

    return top;

}

int work(int m)

{

	int count,i,j;

	m=graham(m);

	if(m<3) return 0;

	res[++m]=0; count=0;

	for(j=0;j<m;j++)

	{

		count=0;

		for(i=0;i<len;i++)

		{

			if(angle(vertex[res[j]],vertex[leave[i]],vertex[res[j+1]])==0)//找在同一条直线上的点

			    if(++count>=2) break;

		}

		if(count==0) return 0;

	}

    return 1;

}

int rePoint(int n)

{

	int i,k;

	point p;

	p.x=MAX_INT;

	for(i=0;i<n;i++)

	    if(vertex[i].x<p.x ||  (vertex[i].x==p.x && vertex[i].y<p.y)) 

		{

	    	    p=vertex[i];

		    k=i;

		}

    return k;

}

int main()

{

	int i,m,n,k;

	point temp;

	scanf("%d",&n);

	while(n--)

	{

		scanf("%d",&m);

		for(i=0;i<m;i++)

		{

			scanf("%d%d",&vertex[i].x,&vertex[i].y); 

		}

		if(m<6)

		{

			printf("NO\n");

			continue;

		}

		k=rePoint(m);

                  temp=vertex[k],vertex[k]=vertex[0],vertex[0]=temp;

		

		if(work(m))

		   printf("YES\n");

		else

			printf("NO\n");

	}

	return 0;

}

 

你可能感兴趣的:(poj)