您的位置:首页 > 其它

POJ 1228 Grandpa's Estate 判断原始凸包是否唯一

2012-09-02 22:20 405 查看
题意:给出一个去掉几个点后的凸包,判断剩下的几个点组成的新凸包是不是原来的那个凸包。

分析:只要 新凸包的每条边上有3个或3个以上的点时,凸包就是原来那个凸包,

否则凸包不是原来那个凸包。 很好理解的,不是很难想到。

View Code

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define eps 1e-8

struct point
{
int x, y;
}p[1003];

int det(int x1, int y1, int x2, int y2)
{
return x1 * y2 - x2 * y1;
}

int cross(point o, point a, point b)
{
return det(a.x - o.x, a.y - o.y, b.x - o.x, b.y - o.y);
}

int dblcmp(double x)
{
if( fabs(x) < eps ) return 0;
return x > 0 ? 1 : -1;
}

bool dot_on_seg(point a, point b, point c)  // 判断 点c是否在线段ab上
//我cross写成了int的,注意转换,*1.0, WA点
{
return ( dblcmp( cross(a, b, c)*1.0 ) == 0 )&&  ( dblcmp( (c.x - b.x) * (c.x - a.x) * 1.0 ) <= 0 );
}

bool cmp(point a, point b)
{
if(a.y == b.y) return a.x < b.x;
return a.y < b.y;
}

point res[1003 << 1];
int n, top;

void graham()//凸包,起点和终点是同一个点
{
int i;
sort(p, p + n, cmp);
top = -1;
res[++top] = p[0];
res[++top] = p[1];
for(i = 2; i < n; i++)
{
while(top >= 1 && cross(res[top-1], res[top], p[i]) <= 0)
top--;
res[++top] = p[i];
}
res[++top] = p[n-2];
int t = top;
for(i = n - 3; i >= 0; i--)
{
while(top >= t && cross(res[top-1], res[top], p[i]) <= 0)
top--;
res[++top] = p[i];
}
//for(i = 0; i <= top; i++)
//    printf("%d %d\n", res[i].x, res[i].y);
}

bool judge()
{
if(n <= 5 || top == 1) return 0;
int i, j;
for(i = 0; i < top ; i++)
{
int cnt = 0;
for(j = 0; j < n; j++)
if( dot_on_seg( res[i], res[i+1],p[j]) ) cnt++;
if(cnt < 3) return 0;
}
return 1;
}
int main()
{
int i, j, cas;
scanf("%d", &cas);
while(cas--)
{
scanf("%d", &n);
for(i = 0; i < n; i++)
scanf("%d%d", &p[i].x, &p[i].y);
graham();
puts(judge() ? "YES" : "NO");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: