题目链接:http://poj.org/problem?id=1228
这个题目不好想,开始老是wa,后来不知道改了哪里就AC了
这个题目从样例可以看出给的凸包山的点不是按照顺序来的,是随便的一些点
那么我们就在这些点上建立凸包,那么在建立凸包的时候我们不能随便去掉边
也就是即使是可以去除的点也不能去掉,也就是传统的graphm方法不能预先选择
结束之后要想这个凸包表示唯一那么就不能在外部加任何一个点使其还能长成
一个更大的凸包,这个就要求一个顶点与其前面两个顶点或者后面两个顶点至少
有边能共线,否则你就可以在外面插入一个顶点增加凸包,满足则不能!
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <cmath>
using namespace std;
#define eps 1e-6
#define PI 3.14159265
struct point
{
double x;
double y;
}po[1500],temp;
int n,pos;
bool zero(double a)
{
return fabs(a) < eps;
}
double dis(point &a,point &b)//返回两点之间距离的平方
{
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
double across(point &a,point &b,point &c)//求a b and a c 的X积
{
return (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
}
int cmp(const void *a,const void *b)
{
int x;
x=across(po[0],*(point*)a,*(point*)b);
if(zero(x))
return dis(po[0],*(point*)a) < dis(po[0],*(point*)b) ? -1 : 1;
return across(po[0],*(point*)a,*(point*)b) > 1e-8 ? -1 : 1;
}
int graham(int num)
{
bool flag=true;
int i,j,k=2;
po[num]=po[0];//fangbian
num++;
for(i=3;i<num;i++)
{
while(across(po[k-1],po[k],po[i]) < -eps)
{k--;}
po[++k]=po[i];//就这个循环结束,不需要了!
}
n=k;
k=0;
for(i=0;i<n;i++)
if(zero(across(po[i],po[i+1],po[i+2])))
{
k=1;
continue;
}
else
{
flag=false;
if(k==0)
{printf("NO\n");k=10;return 0;}
k=0;
}
if(flag)
{
printf("NO\n");
return 0;
}
if(k!=10)
printf("YES\n");
return 0;
}
int main()
{
int i,j,k,t;
point my_temp,temp1;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%lf%lf",&po[0].x,&po[0].y);
temp=po[0];
pos=0;
for(i=1;i<n;i++)
{
scanf("%lf%lf",&po[i].x,&po[i].y);
if(po[i].y < temp.y)
temp=po[i],pos=i;
if(po[i].y==temp.y && po[i].x >temp.x)
{temp1=temp; temp=po[i],pos=i;}
}
temp=temp1;
if(n<6)
{
printf("NO\n");
continue;
}
my_temp=po[0];
po[0]=po[pos];
po[pos]=my_temp;
qsort(po+1,n-1,sizeof(po[0]),cmp);
graham(n);
}
return 0;
}