zoukankan      html  css  js  c++  java
  • 「二维凸包」学习笔记

    何为凸包

    凸包也就是类似求这样一个东西:

    给出一个点集,先在需要找出能围住所有点的一个周长最小的最小凸多边形。也就相当于选出位于最外层的点,将他们连接起来。

    注意凸包是不可能凹的,因为存在一个凹口时,可以连接两边的点,反而让周长更小了

    凸包的求解

    求解凸包一般使用(Andrew)算法

    此算法的大致过程如下:

    将所有点按(x)坐标从小到大排序,并以(y)为第二关键字从小到大排序。然后先做下凸包,上凸包类似

    下凸包的做法是:先将前两个点入栈,然后扫描,每次碰到当前点位于向量((top-1,top))下方时就(pop),直到可以保证凸(不凹)为止

    如何判断一个点在一个向量下方?用叉积即可。由于叉积是乘(sin)的,所以叉积的正负就取决于角度的正负

    时间复杂度:(O(nlogn+2n))

    代码如下

    /*By DennyQi 2018*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define  r  read()
    using namespace std;
    typedef long long ll;
    const int MAXN = 10010;
    const int MAXM = 20010;
    const int INF = 1061109567;
    inline int Max(const int a, const int b){ return (a > b) ? a : b; }
    inline int Min(const int a, const int b){ return (a < b) ? a : b; }
    inline int read(){
        int x = 0; int w = 1; register char c = getchar();
        for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
        if(c == '-') w = -1, c = getchar();
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
    }
    int N;
    struct Coordinate{
    	double x, y;
    };
    Coordinate a[MAXN];
    double ans;
    int top,sta[MAXN];
    inline bool cmp(const Coordinate& a, const Coordinate& b){
    	if(a.x != b.x) return a.x < b.x;
    	return a.y < b.y;
    }
    inline double sqr(const double _X){
    	return _X * _X;
    }
    inline double dist(int _a, int _b){
    	double x1 = a[_a].x, y1 = a[_a].y;
    	double x2 = a[_b].x, y2 = a[_b].y;
    	return sqrt(sqr(x1-x2)+sqr(y1-y2));
    }
    inline double Cross(int _a, int _b, int _c){
    	double x1 = a[_b].x-a[_a].x, y1 = a[_b].y-a[_a].y;
    	double x2 = a[_c].x-a[_a].x, y2 = a[_c].y-a[_a].y;
    	return x1*y2 - x2*y1;
    }
    inline void ConvexHull(){
    	sort(a+1, a+N+1, cmp);
    	top = 2;
    	sta[1] = 1, sta[2] = 2;
    	ans = dist(sta[1], sta[2]);
    	for(int i = 3; i <= N; ++i){
    		while(top > 1 && Cross(sta[top-1],i,sta[top]) > 0){
    			ans -= dist(sta[top-1], sta[top]);
    			--top;
    		}
    		ans += dist(sta[top],i);
    		sta[++top] = i;
    	}
    	top = 2;
    	sta[1] = N, sta[2] = N-1;
    	ans += dist(sta[1], sta[2]);
    	for(int i = N-2; i > 0; --i){
    		while(top > 1 && Cross(sta[top-1],i,sta[top]) > 0){
    			ans -= dist(sta[top-1], sta[top]);
    			--top;
    		}
    		ans += dist(sta[top],i);
    		sta[++top] = i;
    	}
    }
    int main(){
    	scanf("%d", &N);
    	for(int i = 1; i <= N; ++i){
    		scanf("%lf %lf", &a[i].x, &a[i].y);
    	}
    	ConvexHull();
    	printf("%.2f", ans);
    	return 0;
    }
    
  • 相关阅读:
    事以密成,能者低调
    时间过得真快,一晃三年过去了
    读书随记2011111
    Makefile
    ubuntu 7 下 tftp 的配置
    uboot移植到nano2410
    ubuntu 7.04 Feisty Fawn 安装手记之五:安装常用软件
    移植linux2.6.18到arm9
    移植busybox 1.4.2
    UBoot中SMDK2410的NAND Flash驱动。
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9565712.html
Copyright © 2011-2022 走看看