“稳定”凸包----poj1228

   题目链接: http://poj.org/problem?id=1228

   这道题算是很好的一道凸包的题吧,做完后会加深对凸包的理解。

   题意很关键。。。这英语看了好几遍才差不多看明白了。意思就是给你一堆点,这堆点本来就是某个凸包上的部分点,问你这堆点是否能确定唯一的凸包(大概这意思吧。。。)。后来搜了一下,发现这种凸包叫做稳定凸包。

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

“稳定”凸包----poj1228这四个点是某个凸包上的部分点,他们连起来后确实还是一个凸包。但是原始的凸包可能不是这样。比如:“稳定”凸包----poj1228

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

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

“稳定”凸包----poj1228

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

     写的时候又遇到几个小问题了。。。一个是要修改一下凸包模板,大多数人的模板都是不包括共线点的。然后,如果输入的点数n小于6,那么直接输出NO。当然,也可以直接按极角排序进行比较。至于判断一条边上是否至少有三个点,我是这样做的,假设要判断的边i,那么判断边i和边i-1,边i和边i+1的夹角是否都为0(180)。

    代码~:

 1 //POJ--1228

 2 #include <iostream>

 3 #include <cstdio>

 4 #include <cmath>

 5 #include <cstring>

 6 #include <algorithm>

 7 #define  eps 1e-8

 8 using namespace std;

 9 

10 struct  point

11 {

12     double x,y;

13 };

14 point p[1010],stack[1010];

15 int N,top;

16 

17 double multi(point p1, point p2, point p3)  

18 {

19     return (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);

20 }

21 

22 double dis(point a, point b)

23 {

24     return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));

25 }

26 

27 int cmp(const void *a, const void *b)

28 {

29     point c = *(point *)a;

30     point d = *(point *)b;

31     double k = multi(p[0], c, d);

32     if(k < 0 || (!k && dis(c, p[0]) > dis(d, p[0])))    return 1;

33     return -1;

34 }

35 

36 void Convex()

37 {

38     for(int i = 1; i < N; i++)

39     {

40         point temp;

41         if(p[i].y < p[0].y || ( p[i].y == p[0].y && p[i].x < p[0].x))

42         {

43             temp = p[i];

44             p[i] = p[0];

45             p[0] = temp;

46         }

47     }

48     qsort(p + 1, N - 1, sizeof(p[0]), cmp);

49     stack[0] = p[0];

50     stack[1] = p[1];

51     top = 1;

52     for(int i = 2; i < N; i++)     

53     {

54         while(top >= 1 && multi(stack[top - 1], stack[top], p[i]) < 0)     top--;         //共线的点也压入凸包内;

55         top++;

56         stack[top] = p[i];

57     }

58 }

59 

60 bool judge()

61 {

62     for(int  i=1;i<top;i++)

63     {

64         if((multi(stack[i-1],stack[i+1],stack[i]))!=0&&(multi(stack[i],stack[i+2],stack[i+1]))!=0)          //判断每条边是否有至少三个点;

65             return false;

66     }

67     return true;

68 }

69 

70 int main()

71 {

72     int t;

73     cin>>t;

74     while(t--)

75     {

76         cin>>N;

77         for(int i=0;i<N;i++)

78         scanf("%lf%lf",&p[i].x,&p[i].y);

79         if(N<6)   puts("NO");

80         else 

81         {

82                 Convex();

83                 if(judge())  puts("YES");

84                 else puts("NO");

85         }

86     }

87     return 0;

88 }

 

 

 

 

 

 

你可能感兴趣的:(poj)