Grandpa's Estate
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 12204 | Accepted: 3430 |
Description
Being the only living descendant of his grandfather, Kamran the Believer inherited all of the grandpa's belongings. The most valuable one was a piece of convex polygon shaped farm in the grandpa's birth village. The farm was originally separated from the neighboring farms by a thick rope hooked to some spikes (big nails) placed on the boundary of the polygon. But, when Kamran went to visit his farm, he noticed that the rope and some spikes are missing. Your task is to write a program to help Kamran decide whether the boundary of his farm can be exactly determined only by the remaining spikes.
Input
The first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains an integer n (1 <= n <= 1000) which is the number of remaining spikes. Next, there are n lines, one line per spike, each containing a pair of integers which are x and y coordinates of the spike.
Output
There should be one output line per test case containing YES or NO depending on whether the boundary of the farm can be uniquely determined from the input.
Sample Input
1 6 0 0 1 2 3 4 2 0 2 4 5 0
Sample Output
NO
题目难懂.
题意:稳定凸包问题:给出n个点,问形成的凸包是否"稳定"。
所谓稳定就是判断能不能在原有凸包上加点,得到一个更大的凸包,并且这个凸包包含原有凸包上的所有点。
这个解释感觉容易懂,引自:http://blog.csdn.net/acdreamers/article/details/10023615/
我的看法其实就是一条边上要除了顶点外至少还要一个点.那样的话才会稳定.
以我之拙见。。网上的解法是有问题的。。给出我的解法和别人的一组测试数据。POJ的数据可能水了点..网上的解法很多都是将在凸包上边上但不是顶点的点加进去。然后再用两个叉积条件判断。
我是直接枚举每条边,然后枚举所有点,除了顶点之外至少还要有一个点在边上才行(题目说了点都在凸包顶点或者边上,,这样更说明了如果用网上的解法去求凸包是没有意义的,因为已经排好序了,所有的点再加一次,Stack应该就是p了)。
还要加个条件就是点数不能小于6,因为就算是三角形都至少需要6个点才稳定。
测试数据:
1
6
0 0 1 1 2 2 3 3 2 3 0 3
NO
#include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <algorithm> #include <stdlib.h> using namespace std; const int N = 1005; const double eps = 1e-8; struct Point { int x,y; }p[N],Stack[N]; struct Line{ Point a,b; }line; int n; int cross(Point a,Point b,Point c){ return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x); } double dis(Point a,Point b){ return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))); } int cmp(Point a,Point b){ if(cross(a,b,p[0])>0) return 1; if(cross(a,b,p[0])==0&&dis(b,p[0])-dis(a,p[0])>eps) return 1; return 0; } bool Graham(){ int k=0; for(int i=1;i<n;i++){ if(p[i].y<p[k].y||(p[i].y==p[k].y)&&(p[i].x<p[k].x)) k=i; } swap(p[0],p[k]); sort(p+1,p+n,cmp); int top =2; Stack[0] = p[0]; Stack[1] = p[1]; Stack[2] = p[2]; for(int i=3;i<n;i++){ while(top>=1&&cross(p[i],Stack[top],Stack[top-1])>=0) top--; Stack[++top] = p[i]; } int cnt ; Stack[top+1] = Stack[0]; for(int i=0;i<=top;i++){ line.a = Stack[i]; line.b = Stack[i+1]; cnt =0; for(int j=0;j<n;j++){ if(line.a.x == p[j].x && line.a.y == p[j].y) continue; ///除去自身 if(line.b.x == p[j].x && line.b.y == p[j].y) continue; if(cross(line.a,line.b,p[j])==0){ cnt++; break; } } if(cnt==0) return false; } return true; } int main() { int tcase; scanf("%d",&tcase); while(tcase--){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%d",&p[i].x,&p[i].y); } if(n<6){ printf("NO ");continue; } bool ans = Graham(); if(ans) printf("YES "); else printf("NO "); } return 0; }