zoukankan      html  css  js  c++  java
  • POJ 1228 (稳定凸包问题)

    <题目链接>

     <转载于  >>> >

    首先来了解什么是稳定的凸包。比如有4个点:

    这四个点是某个凸包上的部分点,他们连起来后确实还是一个凸包。但是原始的凸包可能不是这样。

    比如:

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

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

    于是此题的做法就很明确了,就是在给出的点中,找到凸包,并且判断这个凸包是不是每条边至少有三个点。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 #define  eps 1e-8
     7 using namespace std;
     8 
     9 struct  point{
    10     double x,y;
    11 };
    12 point p[1010],stack[1010];
    13 int N,top;
    14 double multi(point p1, point p2, point p3){   //向量(p1->p2)^(p1->p3)
    15     return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
    16 }
    17 double dis(point a, point b){
    18     return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    19 }
    20 int cmp(const void *a, const void *b){    //按极角排序
    21     point c = *(point *)a;
    22     point d = *(point *)b;
    23     double k = multi(p[0], c, d);
    24     if(k < 0 || (!k && dis(c, p[0]) > dis(d, p[0])))   return 1;
    25     return -1;
    26 }
    27 void Convex(){    //凸包的构建  Andrew算法
    28     for(int i = 1; i < N; i++){    //先按x,y坐标排序,找到原点   
    29         point temp;
    30         if(p[i].y < p[0].y || ( p[i].y == p[0].y && p[i].x < p[0].x)){
    31             temp = p[i];
    32             p[i] = p[0];
    33             p[0] = temp;
    34         }
    35     }
    36     qsort(p + 1, N - 1, sizeof(p[0]), cmp);  //再将除原点以外的点按极角排序
    37     stack[0] = p[0];         //先将起始的两个点压入栈内,在进行后面的判断
    38     stack[1] = p[1];
    39     top = 1;
    40     for(int i = 2; i < N; i++){
    41         while(top >= 1 && multi(stack[top - 1], stack[top], p[i]) < 0)top--;         //共线的点也压入凸包内;
    42         top++;
    43         stack[top] = p[i];
    44     }
    45 }
    46 bool judge(){    //这个函数是关键
    47     for(int i=1;i<top;i++){
    48         if((multi(stack[i-1],stack[i+1],stack[i]))!=0&&(multi(stack[i],stack[i+2],stack[i+1]))!=0) //判断每条边是否有至少三个点,即判断i-1,i,i+1这三个点是否在一条直线上或者i,i+1,i+2是否在一条直线上
    49             return false;
    50     }
    51     return true;
    52 }
    53 int main(){
    54     int t;
    55     cin>>t;
    56     while(t--){
    57         cin>>N;
    58         for(int i=0;i<N;i++)
    59         scanf("%lf%lf",&p[i].x,&p[i].y);
    60         if(N<6)puts("NO");
    61         else{
    62             Convex();
    63             if(judge())puts("YES");
    64             else puts("NO");
    65         }
    66     }
    67     return 0;
    68 }

    2018-08-23

  • 相关阅读:
    ssd 的anchor生成详解
    Qt小技巧8.利用反射机制通过类名创建Qt对象
    项目经验2.需求才是王道
    Qt实战12.可自由展开的ToolBox
    Qt实战11.进程窗口集成之假装写了个第三方软件
    Qt小技巧7.Qt4集成fusion风格
    Qt杂谈3.快速体验Qt for Android(windows平台)
    Qt实战10.支持最小化和最大化的QDockWidget
    gitlab 拉取远程分支代码
    CentOS7下用jdk1.7编译hadoop-2.7.1全过程详解
  • 原文地址:https://www.cnblogs.com/00isok/p/9522283.html
Copyright © 2011-2022 走看看