• HDOJ1392 Surround the Trees


      原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=1392

      以下内容转自  http://dev.gameres.com/Program/Abstract/Geometry.htm#凸包的求法

      求凸包。

    凸包的概念:
     
      点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。下图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。

     
    凸包的求法:
     
      现在已经证明了凸包算法的时间复杂度下界是O(n*logn),但是当凸包的顶点数h也被考虑进去的话,Krikpatrick和Seidel的剪枝搜索算法可以达到O(n*logh),在渐进意义下达到最优。最常用的凸包算法是Graham扫描法和Jarvis步进法。本文只简单介绍一下Graham扫描法,其正确性的证明和Jarvis步进法的过程大家可以参考《算法导论》。
     
     对于一个有三个或以上点的点集Q,Graham扫描法的过程如下:
     
     令p0为Q中Y-X坐标排序下最小的点 
     设<p1,p2,...pm>为对其余点按以p0为中心的极角逆时针排序所得的点集(如果有多个点有相同的极角,除了距p0最远的点外全部移除)
      压p0进栈S
      压p1进栈S
      压p2进栈S
        for i ← 3 to m
          do while 由S的栈顶元素的下一个元素、S的栈顶元素以及pi构成的折线段不拐向左侧
            对S弹栈
          压pi进栈S
        return S;
     
      此过程执行后,栈S由底至顶的元素就是Q的凸包顶点按逆时针排列的点序列。需要注意的是,我们对点按极角逆时针排序时,并不需要真正求出极角,只需要求出任意两点的次序就可以了。而这个步骤可以用矢量叉积性质实现。(ps:其实凸包顺时针扫描或者逆时针扫描依据个人爱好决定,不同部分只需要改动排序顺序和矢量叉积即可)
    View Code
     1 /*
     2     Author: bcegkmqsw
     3 */
     4 #include <cstdio>
     5 #include <cstdlib>
     6 #include <cmath>
     7 
     8 const double eps = 1e-8;
     9 
    10 struct Point
    11 {
    12     double x, y;
    13 }points[101], res[101];
    14 
    15 inline int dcmp(double d) // 浮点误差处理
    16 {
    17     if(fabs(d) < eps) return 0;
    18     return d > 0 ? 1 : -1;
    19 }
    20 
    21 inline double det(double x1, double y1, double x2, double y2)  // 计算叉积
    22 {
    23     return x1 * y2 - x2 * y1;
    24 }
    25 
    26 inline double cross(Point a, Point b, Point c)  // 右手螺旋为正
    27 {
    28     return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y);
    29 }
    30 
    31 int cmp(const void *a, const void *b)   // Y-X型坐标排序
    32 {
    33     
    34     if(!dcmp((*(Point *)a).y - (*(Point *)b).y))
    35         return dcmp((*(Point *)a).x - (*(Point *)b).x);
    36     return dcmp((*(Point *)a).y - (*(Point *)b).y);
    37 }
    38 
    39 int Graham(Point p[], Point res[], int n, int &top)  // 求凸包,结果为逆时针顺序
    40 {
    41     int len, i;
    42     top = 1;
    43     qsort(p, n, sizeof(Point), cmp);
    44     res[0] = p[0], res[1] = p[1];
    45     for(i = 2; i < n; i ++)
    46     {
    47         while(top && cross(res[top], res[top - 1], p[i]) <= 0) // 不拐向右侧就出栈(求出从底到顶,凸包左半部分)
    48             -- top;
    49         res[++ top] = p[i];
    50     }
    51     len = top;
    52     res[++ top] = p[n - 2];
    53     for(i = n - 3; i >= 0; -- i)
    54     {
    55         while(top != len && cross(res[top], res[top - 1], p[i]) <= 0) // 不拐向右侧就出栈(求出从顶到底,凸包右半部分)
    56             -- top;
    57         res[++ top] = p[i];
    58     }
    59     return top;
    60 }
    61 
    62 int main()
    63 {
    64     int n, i, top;
    65     Point tmp;
    66     double len;
    67     while(scanf("%d", &n), n)
    68     {
    69         len = 0.0;
    70         for(i = 0; i < n; i++)
    71             scanf("%lf%lf", &points[i].x, &points[i].y);
    72         if(n == 1)
    73         {
    74             printf("%.2lf\n", len);
    75             continue;
    76         }
    77         else if(n == 2)
    78         {
    79             len = sqrt((points[1].x - points[0].x) * (points[1].x - points[0].x) + (points[1].y - points[0].y) * (points[1].y - res[0].y));
    80             printf("%.2lf\n", len);
    81             continue;
    82         }
    83         
    84         Graham(points, res, n, top);
    85         
    86         Point a, b;
    87         
    88         for(i = top; i > 1; i --)
    89         {
    90             a = res[i], b = res[i - 1];
    91             len += sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    92         }
    93         len += sqrt((res[1].x - res[top].x) * (res[1].x - res[top].x) + (res[1].y - res[top].y) * (res[1].y - res[top].y));
    94         printf("%.2lf\n", len);
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    ASP.NET 2.0 X64的奇怪问题
    【分享】从网上爬的WPF学习资料
    大家一起学习less 5:字符串插值
    大家一起学习less 3:命名空间
    我的模块加载系统 v18
    大家一起学习less 2:自带函数
    “计算机之子”的MVVM框架源码学习笔记
    我的MVVM框架 v0.1发布
    大家一起学习less 6:一些有用的混合函数
    less源码学习
  • 原文地址:https://www.cnblogs.com/huangfeihome/p/2685383.html
Copyright © 2020-2023  润新知