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 < 0) return -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 == 0) return ;stack[top++] = 0;
52 if(n == 1) return ;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 }
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 < 0) return -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 == 0) return ;stack[top++] = 0;
52 if(n == 1) return ;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 }