zoukankan      html  css  js  c++  java
  • 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;
    }
    

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    遗传算法-目标函数与适应度函数变换
    遗传算法-编码
    Python 绘制甘特图
    fiddler抓包
    使用msf查询补丁和可利用提权漏洞
    Shodan入坑指南
    python 项目自动生成requirements.txt文件
    Tomcat 基于端口的虚拟主机配置
    python简单搭建http server
    metasploit后渗透 之 portfwd端口重定向
  • 原文地址:https://www.cnblogs.com/wanglaoda/p/4937160.html
Copyright © 2011-2022 走看看