zoukankan      html  css  js  c++  java
  • 计算几何 二维凸包问题 Andrew算法

    凸包:把给定点包围在内部的、面积最小的凸多边形。

    Andrew算法是Graham算法的变种,速度更快稳定性也更好。

    首先把全部点排序。依照第一keywordx第二keywordy从小到大排序,删除反复点后得到点序列P1...Pn。

    1)把P1,P2放入凸包中,凸包中的点使用栈存储

    2)从p3開始,当下一个点在凸包当前前进方向(即直线p1p2)左边的时候继续;

    3)否则依次删除近期增加凸包的点,直到新点在左边。



    如图,新点P18在当前前进方向P10P15的右边(使用叉积推断),因此须要从凸包上删除点P15和P10。让P8的下一个点为P18。反复该过程直到碰到最右边的Pn,求出下凸包即凸包的下轮廓。然后从Pn反过来反复该步骤求出上凸包,合并起来后就是完整的凸包。


    该算法扫描为O(n)复杂度,排序O(nlogn)。

    C++ code(刘汝佳《算法竞赛入门经典-训练指南》模板)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const double eps = 1e-8,Pi=3.14159265;
    
    int n;
    
    inline int dcmp(double x)//三态函数
    {
    	if(fabs(x) < eps)	return 0;
    	else return x>0 ?

    1 : -1; } #define Vector Point struct Point { double x,y; inline Point(double x=0,double y=0):x(x),y(y) {} }p[10000+5],ch[10000+5]; bool myCmp(Point A, Point B) { if(A.x != B.x) return A.x < B.x; else return A.y < B.y; } Vector operator + (Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);} Vector operator - (Vector A, Vector B) {return Vector(A.x - B.x, A.y - B.y);} bool operator == (const Vector& A, const Vector& B) {return dcmp(A.x-B.x)==0 && dcmp(A.y-B.y)==0;} inline double Cross(Vector A, Vector B)//叉积 { return A.x * B.y - A.y * B.x; } int ConvexHull() { sort(p,p+n,myCmp); int m = 0; for(int i = 0; i <n; i++) { while(m > 1 && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--; ch[m++] = p[i]; } int k = m; for(int i = n-2; i >= 0; i--) { while(m > k && dcmp(Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2])) <= 0) m--; ch[m++] = p[i]; } if(n > 1) m--; return m; } double Dis(Point A, Point B) { return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y)); } int main() { int m; cin>>n; for(int i = 0; i < n; i++) { int a,b; cin>>a>>b; p[i] = Point(a,b); } m = ConvexHull(); //计算凸包周长 double ans=0.0; for(int i = 0; i < m-1; i++) ans += Dis(ch[i],ch[i+1]); ans += Dis(ch[m-1],ch[0]); printf("%.1f",ans); }


    例题:

    wikioi1298(click me)

    求解二维凸包并计算周长

    wikioi3201(click me)

    求解二维凸包并计算周长

    poj1113(click me)

    本题翻译:http://blog.csdn.net/lytning/article/details/24046075

    求解二维凸包并增加一个圆的周长


  • 相关阅读:
    react native配置ip真机测试
    APP Store上架QA&注意事项
    iOS 开发】解决使用 CocoaPods 执行 pod install 时出现
    iphoneX适配!!!
    better-scroll和swiper使用中的坑
    js知识巩固
    vue的学习(常用功能)
    vue学习生命周期(created和mounted区别)
    jq常用功能操作
    移动端中遇到的坑(bug)!!!
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7255457.html
Copyright © 2011-2022 走看看