poj1228 [ SDOI2009 ] --稳定凸包

题目大意:给你一个凸包上的某些点(可能在凸包内),询问是否能确定这个凸包。

 

思路:先求出题目给出的点的凸包,看看在凸包的每条边内(不包括端点)有没有点,若有,则这条边是确定的,若没有,则这条边不确定,直接输出NO。这里用Andrew求凸包。

 

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct point{
    double x,y;
    point(double x=0,double y=0):x(x),y(y){}
}a[1001],ch[1001];
point operator - (point a,point b){
    return point(a.x-b.x,a.y-b.y);
}
int i,j,k,n,m,t;
double cross(point a,point b){
    return a.x*b.y-a.y*b.x;
}
bool cmp(point a,point b){
    return a.x<b.x||(a.x==b.x&&a.y<b.y)?1:0;
}
bool check(point a,point b){
    return a.x!=b.x||a.y!=b.y?1:0;
}
int main()
{
    scanf("%d",&t);
    for(int p=0;p<t;p++){
        m=0;
        scanf("%d",&n);
        for(i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
        if(n<6){
            printf("NO\n");
            continue;
        }
        sort(a+1,a+n+1,cmp);
        for(i=1;i<=n;i++){
            while(m>1&&cross(ch[m]-ch[m-1],a[i]-ch[m-1])<=0)m--;
            ch[++m]=a[i];
        }
        k=m;
        for(i=n-1;i>=1;i--){
            while(m>k&&cross(ch[m]-ch[m-1],a[i]-ch[m-1])<=0)m--;
            ch[++m]=a[i];
        }
        for(i=1;i<m;i++){
            for(j=1;j<=n;j++)
            if(check(ch[i],a[j])&&check(ch[i+1],a[j]))
            if(((a[j].x>=ch[i].x&&a[j].x<=ch[i+1].x)||(a[j].x<=ch[i].x&&a[j].x>=ch[i+1].x))&&!cross(ch[i+1]-ch[i],a[j]-ch[i]))break;
            if(j==n+1)break;
        }
        if(i<m)printf("NO\n");else printf("YES\n");
    }
    return 0;
}

 

posted @ 2016-07-29 20:41  gjghfd  阅读(213)  评论(0编辑  收藏  举报