zoukankan      html  css  js  c++  java
  • HDU 1392 Surround the Trees(凸包*计算几何)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1392

    这里介绍一种求凸包的算法:Graham。(相对于其它人的解释可能会有一些出入,但大体都属于这个算法的思想,同样可以解决凸包问题)

    相对于包裹法的n*m时间,Graham算法在时间上有很大的提升,只要n*log(n)时间就够了。它的基本思想如下:

    1、首先,把所有的点按照y最小优先,其次x小的优先排序

    2、维护一个栈,用向量的叉积来判断新插入的点跟栈顶的点哪个在外围,如果栈顶的点在当前插入的点的左边,那么把栈顶的这个元素弹出,弹出之后不能继续插入下一个点,要继续判断当前插入点跟弹出之后的栈顶的点的位置关系,当当前插入的点在栈顶的那个点的左边时,则可以将要插入的点压到栈中,进入下一个点。

    对于这题,最后要计算的是凸包的边长,所以最后别忘了加上最后一个点到第一个点的距离。还有只有一个点和两个点的情况时要进行特判。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int maxn = 105;
     8 struct point
     9 {
    10     double x,y;
    11     point(double x = 0,double y = 0):x(x),y(y) {}
    12     friend  point operator + (point p1,point p2)
    13     {
    14         return point(p1.x+p2.x,p1.y+p2.y);
    15     }
    16     friend  point operator - (point p1,point p2)
    17     {
    18         return point(p1.x-p2.x,p1.y-p2.y);
    19     }
    20     
    21 }p[maxn],res[maxn];
    22 double dis(point p1,point p2)
    23 {
    24     return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
    25 }
    26 double dot(point p1,point p2)
    27 {
    28     return p1.x*p2.y - p2.x*p1.y;
    29 }
    30 bool cmp(point p1,point p2)
    31 {
    32     if(p1.y == p2.y) return p1.x < p2.x;
    33     return p1.y < p2.y;
    34 }
    35 int graham(point* p,int n,point* res)
    36 {
    37     sort(p,p+n,cmp);
    38     res[0] = p[0];
    39     res[1] = p[1];
    40 //    res[2] = p[2];
    41     int top = 1,len;
    42     for(int i = 2;i < n;++i)
    43     {
    44         while(top && dot(p[i]-res[top-1],res[top]-res[top-1]) >= 0) top--;
    45         res[++top] = p[i];
    46     }
    47     len = top;
    48     for(int i = n-1;i >= 0;--i)
    49     {
    50         while(top != len && dot(p[i]-res[top-1],res[top]-res[top-1]) >= 0) top--;
    51         res[++top] = p[i];
    52     }
    53     return top;
    54 }
    55             
    56 int main()
    57 {
    58 //    freopen("in.txt","r",stdin);
    59     int n;
    60     while(scanf("%d",&n),n)
    61     {
    62         for(int i = 0;i < n;++i)
    63         scanf("%lf%lf",&p[i].x,&p[i].y);
    64         if(n == 1)
    65         {
    66             printf("0.00
    ");
    67             continue;
    68         }
    69         if(n == 2)
    70         {
    71             printf("%.2lf
    ",dis(p[0],p[1]));
    72             continue;
    73         }
    74         int m = graham(p,n,res);
    75         double tot = 0;
    76         for(int i = 1;i <= m;++i)
    77         tot += dis(res[i-1],res[i]);
    78         printf("%.2lf
    ",tot);
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    学到了林海峰,武沛齐讲的Day63 网页制作思路 Toando 自定义form验证
    学到了林海峰,武沛齐讲的Day62 SONP实现AJax跨域 Iframe文件上传
    学到了林海峰,武沛齐讲的Day60 Form组件中的源码添加详解 gjango序列化 数据库取值转换
    学到了林海峰,武沛齐讲的Day59 Form组件
    学到了林海峰,武沛齐讲的Day58 分页 初识Form
    学到了林海峰,武沛齐讲的Day57 表单实战讲解
    学到了林海峰,武沛齐讲的Day56 表单实战讲解
    学到了林海峰,武沛齐讲的Day58 分页 form表单
    最详细的正则(转载)
    爬虫笔记(二):爬取药监局所有详情页数据
  • 原文地址:https://www.cnblogs.com/xiaxiaosheng/p/4105547.html
Copyright © 2011-2022 走看看