poj1228 - Grandpa's Estate

133 篇文章 0 订阅

                                想看更多的解题报告:http://blog.csdn.net/wangjian8006/article/details/7870410
                                  转载请注明出处:
http://blog.csdn.net/wangjian8006

 题目大意:原本有一些点围成了一个凸多边形,你不知道原来是什么样子的,现在又 给出一些点,确保这些点都是凸包上的点(不会在以前的凸包的里面), 现在问你这些点围成的形状是否可以确定原来那些点围成的凸多边形

 解题思路:由于我们知道现在给的点全是凸包上的点,所以我们看现在的这个凸包的【顶点】中间有没有其他的点,如果至少有一点的话,那么这条边就是确定的了,不会再有改变。
 但是如果没有其他点,那么两个顶点是不能确定原来的那个凸多边形的形状的,因为两个点之间以前还可以存在某些点没在这条边上。
 所以我们只需要将给的凸包点算出凸包顶点,然后再判断两相邻顶点之间有没其他点就可以了

 

/*
Memory 188K
Time   16MS 
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define MAXV 1010
#define INF 1e8

struct Point{
    double x,y;
}point[MAXV],tmp;

int n,d[MAXV],dtop;

double distance(double x1,double y1,double x2,double y2){
    double dis=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
    return sqrt(dis);
}

double chaji(struct Point a1,struct Point b1,struct Point a2,struct Point b2){  //求<a1,b1>向量和<a2,b2>向量的叉积
    double x1=b1.x-a1.x;
    double y1=b1.y-a1.y;
    double x2=b2.x-a2.x;
    double y2=b2.y-a2.y;
    return x1*y2-x2*y1;
}

int cmp(const void *p1,const void *p2){
    struct Point *a=(struct Point *)p1;
    struct Point *b=(struct Point *)p2;
    double flag=chaji(point[0],*a,point[0],*b);
    if(flag>0)   return -1;
    else if(!flag && distance((a->x),(a->y),point[0].x,point[0].y)<distance((b->x),(b->y),point[0].x,point[0].y))
        return -1;
    return 1;
}

int findminp(){
    int i,v;
    double ymin=INF,xmin=INF;
    for(i=0;i<n;i++)
        if(point[i].y<ymin)
            v=i,ymin=point[i].y;

    for(i=0;i<n;i++)
        if(point[i].y==ymin && point[i].x<xmin)
            v=i,xmin=point[i].x;
    return v;
}

void graham(){
    int i;
    dtop=0;
    d[dtop++]=0;
    d[dtop++]=1;
    for(i=2;i<n;i++){
        while(chaji(point[d[dtop-2]],point[d[dtop-1]],point[d[dtop-1]],point[i])<0) dtop--;
        d[dtop++]=i;
    }
}
int main(){
    int t,h,i,j,flag,sum;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(i=0;i<n;i++) scanf("%lf%lf",&point[i].x,&point[i].y);
        if(n<=5) {printf("NO\n");continue;}
        h=findminp();
        tmp=point[0];
        point[0]=point[h];
        point[h]=tmp;
        qsort(point+1,n-1,sizeof(point[0]),cmp);
        graham();			//求出凸包

         flag=1;				//看凸包上【顶点】的中间有没有其他点,如果有一条没有就是NO
        sum=0;
        for(i=1;i<dtop;i++){
            for(j=0;j<n;j++)
                if(j!=d[i] && j!=d[i-1] && !chaji(point[d[i-1]],point[d[i]],point[d[i-1]],point[j])){
                        break;
                }
            if(j==n) sum++;
        }
        for(j=0;j<n;j++)
                if(j!=d[0] && j!=d[i-1] && !chaji(point[d[0]],point[d[i-1]],point[d[0]],point[j])){
                        break;
                }
        if(j==n) sum++;

        if(sum>0) flag=0;

        if(flag) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值