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;
}
浙公网安备 33010602011771号