POJ 1228 Grandpa's Estate(给定凸包上的一部分顶点 判断表示的凸包是否唯一)

题目链接: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值