• 凸包 Gramham 扫描法


    今天突然看见凸包题,然后翻看自己以前学的时候写的博客,竟然发现那个学习的链接没了,就去看了算法导论,然后对着模板,把这个算法看了一遍,东西还是要多看几遍的,每次看都有不同的感受,总会有那么一次,你会发出一句感慨:呃,原来是这样啊!现在把模板整理一下吧

    先说一下求解步骤:

    1.首先在输入的点集中找出一个对照点,放入到 p[0]中,这个对照点就是 在点集的最下,最左的那个点

    2.对 1 ~ n - 1的点按相对于 对照点的极角从小到大排序,如果极角相同那么就按距离对照点的远近从小到大排序

    3.把输入的点集的前两个点放入到栈中,然后依次扫描剩余的点,把不是凸包顶点的点从栈中剔除,沿逆时针方向通过凸包时,在每个顶点处应该左转,因此,如果发现在顶点处没有左转,就可以从栈里弹出了,把向左转的点加入到栈中

    最后栈里面保存的就是凸包的顶点

    View Code
     1 struct node
     2 {
     3     int x,y;
     4 }point[N],stack[N];
     5 int top,n;
     6 int pows(int x)
     7 {
     8     return x * x;
     9 }
    10 double dis(node a,node b)
    11 {
    12     return sqrt((double)(pows(a.x - b.x) + pows(a.y - b.y)));  // 计算距离
    13 }
    14 double mul(node a,node b,node c)
    15 {
    16     return (c.x - a.x) * (b.y - a.y) - (c.y - a.y) * (b.x - a.x); // 叉积判断方向和计算极角
    17 }
    18 int cmp(const void *a,const void *b)
    19 {
    20     node *c = (node *)a;
    21     node *d = (node *)b;
    22     int m = mul(point[0],*c,*d);
    23     if(m == 0) return dis(*c,point[0]) - dis(*d,point[0]);  // 如果极角为零,那么按距离从小到大排序
    24     else return -m;
    25 }
    26 void gram()
    27 {
    28     int i;
    29     int temp = 0;
    30     for(i = 0; i < n; i++)
    31     {
    32         if(point[i].y < point[temp].y || (point[i].y == point[temp].y && point[i].x < point[temp].x))  // 寻找对照点
    33         temp = i;
    34     }
    35     swap(point[0],point[temp]);  // 保存到 point[0]
    36     qsort(point + 1,n - 1,sizeof(node),cmp); // 排序
    37     top = 1;
    38     stack[0] = point[0];
    39     stack[1] = point[1];
    40     for(i = 2; i < n; i++)
    41     {
    42         while(top >= 1 && mul(stack[top - 1],stack[top],point[i]) <= 0) top--; // 如果在顶点处不是左转那么说明不是凸包的顶点,就剔除
    43         stack[++top] = point[i];  // 左转的点保存到栈里
    44     }
    45 }

    附加两道题目:http://www.cnblogs.com/fxh19911107/archive/2012/05/05/2485214.html

  • 相关阅读:
    回文串---最长回文
    回文串---Hotaru's problem
    回文串--- Girls' research
    回文串---吉哥系列故事——完美队形II
    回文串---Palindrome
    treap树---营业额统计
    treap树---Double Queue
    《程序员代码面试指南》第二章 链表问题 复制含有随机指针节点的链表
    《程序员代码面试指南》第二章 链表问题 将单链表按某值划分为左边小,中间相等,右边大的链表
    《程序员代码面试指南》第二章 链表问题 反转部分单向链表
  • 原文地址:https://www.cnblogs.com/fxh19911107/p/2648116.html
Copyright © 2020-2023  润新知