您的位置:首页 > 其它

POJ 1228 Grandpa's Estate(稳定凸包)

2017-07-03 19:56 381 查看
Grandpa's Estate

Time Limit: 1000MSMemory Limit: 10000K
Total Submissions: 13650Accepted: 3819
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

Source

Tehran 2002 Preliminary

这道题算是很好的一道凸包的题吧,做完后会加深对凸包的理解。

   题意很关键。。。这英语看了好几遍才差不多看明白了。意思就是给你一堆点,这堆点本来就是某个凸包上的部分点,问你这堆点是否能确定唯一的凸包(大概这意思吧。。。)。后来搜了一下,发现这种凸包叫做稳定凸包。

分析:容易知道,当一个凸包稳定时,凸包的每条边上都要有至少三个点,若只有两个点,则可以增加一个点,得到更大的凸包。

那么这道题的做法终于明确了。即求出给定这堆点的新的凸包,然后判断凸包上的每条边上是否至少有3个点存在,假如有一条边不符合条件,则输出NO。否则YES。

   写的时候又遇到几个小问题了。。。一个是要修改一下凸包模板,大多数人的模板都是不包括共线点的。然后,如果输入的点数n小于6,那么直接输出NO。当然,也可以直接按极角排序进行比较。至于判断一条边上是否至少有三个点,我是这样做的,假设要判断的边i,那么判断边i和边i-1,边i和边i+1的夹角是否都为0(180)。
其实我一开始没打算用极点的,就打算用三点共线,但不知道为什么一直WA,那就只能换方法,看看大牛的代码了。

代码出处:http://www.cnblogs.com/xdruid/archive/2012/06/20/2555536.html

AC代码

//POJ--1228
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define  eps 1e-8
using namespace std;

struct  point
{
double x,y;
};
point p[1010],stack[1010];
int N,top;

double multi(point p1, point p2, point p3)
{
return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
}

double dis(point a, point b)
{
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

int cmp(const void *a, const void *b)
{
point c = *(point *)a;
point d = *(point *)b;
double k = multi(p[0], c, d);
if(k < 0 || (!k && dis(c, p[0]) > dis(d, p[0])))    return 1;
return -1;
}

void Convex()
{
for(int i = 1; i < N; i++)
{
point temp;
if(p[i].y < p[0].y || ( p[i].y == p[0].y && p[i].x < p[0].x))
{
temp = p[i];
p[i] = p[0];
p[0] = temp;
}
}
qsort(p + 1, N - 1, sizeof(p[0]), cmp);
stack[0] = p[0];
stack[1] = p[1
4000
];
top = 1;
for(int i = 2; i < N; i++)
{
while(top >= 1 && multi(stack[top - 1], stack[top], p[i]) < 0)     top--;         //共线的点也压入凸包内;
top++;
stack[top] = p[i];
}
}

bool judge()
{
for(int  i=1;i<top;i++)
{
if((multi(stack[i-1],stack[i+1],stack[i]))!=0&&(multi(stack[i],stack[i+2],stack[i+1]))!=0)          //判断每条边是否有至少三个点;
return false;
}
return true;
}

int main()
{
int t;
cin>>t;
while(t--)
{
cin>>N;
for(int i=0;i<N;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
if(N<6)   puts("NO");
else
{
Convex();
if(judge())  puts("YES");
else puts("NO");
}
}
return 0;
}


原题链接:http://poj.org/problem?id=1228
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  凸包 计算几何