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

原文地址:https://www.cnblogs.com/00isok/p/9522283.html