poj 1228 Grandpa's Estate ( 凸包 )

http://poj.org/problem?id=1228 

 

题意:

一块凸包的土地,有若干钉子钉在凸包的边上,现在其中一些钉子掉掉了,判断是否能根据剩下的钉子判断出原来这边凸包的土地,能输出“YES”,不能输出“NO”。 
题解“

首先我们要知道 ,掉了的钉子只能是 边上的点 ,而不能是 拐点,所以我们要,先求其凸包(去除 共线的点),判断每条边上 是否 除了 拐点外 还有 其他的点 ,若没条边除了拐点外都还有其他的点 ,则输出 yes,否则输出 no;

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include<string>
 11 #define Min(a,b) a<b?a:b
 12 #define Max(a,b) a>b?a:b
 13 #define CL(a,num) memset(a,num,sizeof(a));
 14 #define maxn  1010
 15 #define eps  1e-12
 16 #define inf 100000000
 17 #define mx 1<<60
 18 #define ll   __int64
 19 using namespace std;
 20 struct point
 21 {
 22     double x,y;
 23 }p[maxn];
 24 int stack[maxn];
 25 int dblcmp(double x)
 26 {
 27     if(fabs(x) < eps) return 0;
 28     if(x < 0return -1;
 29     else return 1;
 30 }
 31 double det(double x1,double y1,double x2,double y2)
 32 {
 33     return x1*y2 - x2*y1 ;
 34 }
 35 double cross(point a, point b, point c)
 36 {
 37     return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
 38 }
 39 int cmp(point a,point b)
 40 {
 41     if(a.y != b.y) return a.y < b.y;
 42     else return a.x < b.x;
 43 }
 44 int  top ,n,vis[maxn];
 45 void graham()
 46 {
 47     int  i,len;
 48     top = 0;
 49     sort(p,p+n,cmp);
 50 
 51     if(n == 0return ;stack[top++] = 0;
 52     if(n == 1return ;stack[top++] = 1;
 53 
 54     for(i = 2 ;i<n;i++)//求右链
 55     {
 56         while(top&&dblcmp(cross(p[stack[top - 1]],p[stack[top - 2]],p[i])) >= 0) top--;
 57 
 58         stack[top++] = i;
 59     }
 60      //dblcmp(cross(p[stack[top - 1]],p[stack[top - 2]],p[i])) 可以直接是 cross
 61     len =  top ;
 62 
 63     for(i = n - 2;i >= 0;i--)//求左链
 64     {
 65          while(top != len && dblcmp(cross(p[stack[top - 1]],p[stack[top - 2]],p[i])) >= 0)top--;
 66          stack[top++] = i;
 67 
 68     }
 69     top--;//第一个点入栈两次 所以 减 1
 70 
 71 }
 72 int main()
 73 {
 74 
 75       n = 0;
 76       int  i,s,j;
 77     //freopen("data.txt","r",stdin);
 78        int t;
 79        scanf("%d",&t);
 80        while(t--)
 81        {
 82            scanf("%d",&n);
 83            for(i = 0 ;i < n;i++)
 84            {
 85                scanf("%lf%lf",&p[i].x,&p[i].y);
 86            }
 87            if(n < 6)//凸包至少有三个边 ,所以 至少有 6 个点
 88            {
 89                printf("NO\n");
 90                continue ;
 91            }
 92            graham();
 93 
 94            CL(vis,0);
 95            for(i = 0 ; i< top;i++)
 96            {
 97                int sum = 0;
 98                for(j = 0; j < n;j++)
 99                {
100                    if(dblcmp(cross(p[j],p[stack[i]],p[stack[i + 1]])) == 0)
101                    {
102                        sum ++;
103                    }
104                }
105                if(sum < 3) {vis[i] = 1 ;break;}
106            }
107            if(i < top)
108            {
109                 printf("NO\n");
110                 continue ;
111            }
112            else
113            {
114                printf("YES\n");
115                continue ;
116            }
117 
118        }
119 
120 }

 

posted @ 2012-08-28 11:43  Szz  阅读(174)  评论(0编辑  收藏  举报