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

读懂题意很关键,输入一个凸包上的点(没有凸包内部的点,要么是凸包顶点,要么是凸包边上的点),判断这个凸包是否稳定。所谓稳定就是判断能不能在原有凸包上加点,得到一个更大的凸包,并且这个凸包包含原有凸包上的所有点。

首先来了解什么是稳定的凸包。

比如有4个点:

这四个点是某个凸包上的部分点,他们连起来后确实还是一个凸包,但是它们不是稳定的,

我们发现,当凸包上存在一条边上的点只有端点两个点的时候,这个凸包不是稳定的,因为它可以在这条边外再引入一个点,构成一个新的凸包。但一旦一条边上存在三个点,那么不可能再找到一个点使它扩展成一个新的凸包,否则构成的新多边形将是凹的。

下面是一个典型的稳定凸包:

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

自己的不知道哪里有错改不过来了,附上大神代码:

#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];
    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;
}

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

时间: 2024-10-18 16:06:02

POJ 1228 Grandpa's Estate (稳定凸包)的相关文章

POJ 1228 Grandpa&#39;s Estate [稳定凸包]

Grandpa's Estate Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13112   Accepted: 3697 Description Being the only living descendant of his grandfather, Kamran the Believer inherited all of the grandpa's belongings. The most valuable one

poj 1228 Grandpa&#39;s Estate (稳定凸包问题)

---恢复内容开始--- 题意:你的长辈给你留了块土地,然而这块土地是以一些钉子来界定的,题目要做的就是给你一堆钉子的坐标(也就是凸包上部分的点),然后问你能不能唯一确定这块土地 //不得不说知道题意后一脸懵逼.. 知识:稳定凸包 所谓稳定就是判断能不能在原有凸包上加点,得到一个更大的凸包,并且这个凸包包含原有凸包上的所有点. 举一个不稳定的例子 为什么说它不稳定呢?因为他可以加点来得到更大的凸包 那什么样子是稳定的呢? 因此我们可以知道当一个凸包稳定时,凸包的每条边上都要有至少三个点,若只有两

POJ 1228 Grandpa&#39;s Estate --深入理解凸包

题意: 判断凸包是否稳定. 解法: 稳定凸包每条边上至少有三个点. 这题就在于求凸包的细节了,求凸包有两种算法: 1.基于水平序的Andrew算法 2.基于极角序的Graham算法 两种算法都有一个类似下面的语句: for(int i=0;i<n;i++) { while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) <= 0) m--; ch[m++] = p[i]; } 这样的话,求出来就是最简凸包,即点数尽量少的凸包,因

poj 1228 Grandpa&#39;s Estate(凸包)

Grandpa's Estate Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11508   Accepted: 3188 Description Being the only living descendant of his grandfather, Kamran the Believer inherited all of the grandpa's belongings. The most valuable one

【POJ】1228 Grandpa&#39;s Estate(凸包)

http://poj.org/problem?id=1228 随便看看就能发现,凸包上的每条边必须满足,有相邻的边和它斜率相同(即共线或凸包上每个点必须一定在三点共线上) 然后愉快敲完凸包+斜率判定,交上去wa了QAQ.原因是忘记特判一个地方....因为我们求的凸包是三点共线的凸包,在凸包算法中我们叉积判断只是>0而不是>=0,那么会有一种数据为所有点共线的情况,此时求出来的凸包上的点是>原来的点的(此时恰好符合答案NO,因为可以在这条线外随便点一个点就是一个凸包了...)然后特判一下.

POJ1228 Grandpa&#39;s Estate 稳定凸包

POJ1228 转自http://www.cnblogs.com/xdruid/archive/2012/06/20/2555536.html   这道题算是很好的一道凸包的题吧,做完后会加深对凸包的理解.    题意很关键...这英语看了好几遍才差不多看明白了.意思就是给你一堆点,这堆点本来就是某个凸包上的部分点,问你这堆点是否能确定唯一的凸包(大概这意思吧...).后来搜了一下,发现这种凸包叫做稳定凸包. 首先来了解什么是稳定的凸包.比如有4个点: 这四个点是某个凸包上的部分点,他们连起来后

Grandpa&#39;s Estate - POJ 1228(稳定凸包)

刚开始看这个题目不知道是什么东东,后面看了大神的题解才知道是稳定凸包问题,什么是稳定凸包呢?所谓稳定就是判断能不能在原有凸包上加点,得到一个更大的凸包,并且这个凸包包含原有凸包上的所有点.知道了这个东西就简单了,直接求出来凸包后,然后判断每条边上的点是否超过三点就行了. 代码如下: ============================================================================================================

【POJ 1228】Grandpa&#39;s Estate 凸包

找到凸包后暴力枚举边进行$check$,注意凸包是一条线(或者说两条线)的情况要输出$NO$ #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define N 1003 #define read(x) x = getint() using namespace std; inline int getint() { int k = 0, fh = 1; char c

poj 1228(稳定凸包)

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