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 }

 

你可能感兴趣的:(poj)