zoukankan      html  css  js  c++  java
  • 极点的凸包构造算法(extreme point)

    正如其名,通过对点的筛选来构造凸包。

    • 我们从这些点中枚举出所有的三角形,通过对凸包的理解我们知道凸包内部的点可以被包含在某个由极点构成的三角形里面。
    • 我们再从中随意挑选一个还未被筛选成非极点的点,对这个点与三角形进行ToLeftTest,判断这个点是否在三角形里面。
      如果这个点在三角形里面的话,标记这个点为非极点,否则就不进行标记。

    为什么这个筛选是正确的

    我们假定三角形的三个点分别是A, B, C,并且形状如图。

    我们输入三角形的点的顺序可能是如下的

    • ABC
    • ACB
    • BAC
    • BCA
    • CAB
    • CBA

    可以发现,这些点串连起来的顺序要么是顺时针的要么是逆时针的,也就是说:三角形内部的点,要么同时在这三条边的左侧,要么同时在这三条边的右侧。
    当然这里也有一些特殊情况,比如四点共线,三点共线。
    但是以上满足要求的ToLeftTest都不会出现,测试值即出现正数,又出现负数的情况,我们通常就可以认为这种情况下,测试点在三角形外侧。

    代码

    //Powered by CK
    //凸包极点构造
    #include<bits/stdc++.h>
    using namespace std;
    const double INF = 1e100;
    const double pi = acos(-1.0);
    const double eps = 1e-8;
    const int N = 1e5 + 10;
    int n, cnt;
    bool extreme[N];
    struct point {
    	double x, y;
    	point(double a = 0.0, double b = 0.0) : x(a), y(b) {}
    }p[N], ans[N];
    int sgn(double x) {
    	if(fabs(x) < eps)	return 0;
    	if(x < 0)	return -1;
    	return 1;
    }
    point operator - (point a, point b) {
    	return point(a.x - b.x, a.y - b.y);
    }
    double dis(point a, point b) {
    	point temp = a - b;
    	return sqrt(temp.x * temp.x + temp.y * temp.y);
    }
    double cross(point a, point b) {
    	return a.x * b.y - a.y * b.x;
    }
    bool judge(point a, point b, point c, point s) {
    	int flag1 = sgn(cross(b - a, s - a));
    	int flag2 = sgn(cross(c - b, s - b));
    	int flag3 = sgn(cross(a - c, s - c));
    	if(flag1 * flag2 == -1 || flag1 * flag3 == -1 || flag2 * flag3 == -1)	return false;
    	return true;
    }
    bool cmp(point a, point b) {
    	int flag = sgn(cross(a - ans[0], b - ans[0]));
    	if(flag == 1)	return true;
    	if(flag == 0 && dis(a, ans[0]) < dis(b, ans[0]))	return true;
    	return false;	
    }
    void extreme_point() {
    	memset(extreme, true, sizeof extreme);
    	for(int i = 0; i < n; i++)
    		for(int j = i + 1; j < n; j++)
    			for(int k = j + 1; k < n; k++)
    				for(int s = 0; s < n; s++) {
    					if(s == i || s == j || s == k || !extreme[s])	continue;
    					if(judge(p[i], p[j], p[k], p[s]))
    						extreme[s] = false;
    				}
    	for(int i = 0; i < n; i++)
    		if(extreme[i])
    			ans[cnt++] = p[i];
    	sort(ans + 1, ans + cnt, cmp);
    	double target = 0;
    	ans[cnt] = ans[0];
    	for(int i = 0; i < cnt; i++)
    		target += dis(ans[i], ans[i + 1]);
    	printf("%.2f
    ", target);
    }
    int main() {
    	// freopen("in.txt", "r", stdin);
    	scanf("%d", &n);
    	for(int i = 0; i < n; i++)
    		scanf("%lf %lf", &p[i].x, &p[i].y);
    	extreme_point();
    	return 0;
    }
    

    一组凸包周长的测试数据

    这个算法的时间复杂度显然是 O(n^4)的。这里提供一组测试数据供检测算法的正确性。

    这组数据求得的凸包的周长为

    73277.90
    
    170
    -8226.75 9172.55
    -591.55 4936.73
    9919.31 7621.54
    -4789.82 -90.09
    9062.45 -5989.51
    9797.98 -4100.13
    3832.62 -8465.63
    -1456.86 5981.95
    -2118.17 -8618.54
    -813.65 4717.20
    -5377.16 1286.52
    5688.17 -5156.99
    4221.92 339.41
    -1645.44 194.35
    6841.66 40.45
    -9796.55 4884.59
    -7866.19 -8398.81
    9582.46 -1264.16
    -5018.75 -497.22
    -968.48 8962.84
    7489.99 1294.98
    -9595.26 -1905.48
    7228.20 -6342.35
    -3762.82 8161.95
    1724.37 4703.80
    -2638.17 -8880.97
    9206.46 -7470.74
    6771.48 5535.61
    -4408.81 -9974.14
    9745.85 -489.77
    7734.30 -4073.78
    207.60 -136.57
    2911.95 -7881.95
    -6649.46 7561.60
    -5430.82 7193.05
    -5499.17 -605.61
    -5682.64 6250.36
    4232.22 -4086.28
    -9836.22 6955.57
    -263.52 -4397.71
    1013.26 1845.30
    -7558.30 -4689.29
    7408.86 6878.36
    1876.85 -3066.84
    -1482.42 -3757.60
    5788.23 340.63
    -4615.76 3409.22
    6512.12 2555.71
    -9585.73 8439.58
    -6414.58 3187.95
    3118.72 -8467.44
    2615.34 -3891.22
    -7894.79 -7157.41
    -9601.78 7386.98
    3325.03 -1480.12
    6285.34 -541.25
    -5442.80 -6978.48
    -201.18 1568.29
    -3838.25 -2329.84
    4499.64 6440.00
    8057.87 -4547.85
    -1891.40 -6788.82
    -7023.73 2077.35
    -1133.54 -3387.65
    5952.58 3276.44
    -1843.94 2394.09
    60.71 -1636.22
    9371.57 9008.48
    8411.43 -9962.06
    -6973.24 -4461.95
    2393.86 438.61
    -1869.68 -4119.64
    6166.15 -6552.74
    -197.72 -831.90
    7400.13 3247.23
    -6863.51 -3543.26
    4268.06 9124.47
    3324.13 -6348.23
    8693.45 -3479.25
    -7985.71 -9313.48
    5833.96 4345.56
    -63.33 6957.47
    9829.28 -1477.58
    5764.26 -7006.78
    -4207.84 -8200.12
    1236.12 8399.94
    8054.46 9803.03
    2518.24 6021.43
    4646.31 3338.57
    -2175.58 2389.72
    -1943.78 6949.42
    -8715.73 -5613.77
    -7790.58 3718.97
    3058.20 2188.53
    -4282.92 -3671.17
    5703.56 -1568.38
    -8635.25 4361.13
    -3205.27 3654.77
    1857.78 7850.43
    7791.41 7969.98
    -8190.22 -2905.83
    9149.84 -1006.09
    5989.25 8703.68
    -8306.84 -3967.51
    3808.12 7908.75
    4237.83 -9493.05
    -9934.48 -2886.20
    7439.10 -7367.43
    1941.46 -9297.47
    3930.49 4348.84
    -7765.31 -3907.77
    4678.45 -1501.67
    8858.52 1038.57
    -8396.04 4263.95
    -9419.19 7187.02
    -3553.73 -1165.02
    -979.06 9885.78
    -4114.32 5350.47
    6883.88 4228.30
    2905.38 -2932.68
    2459.30 -2627.63
    -5590.64 7801.87
    -9639.25 7083.72
    -4904.64 8595.10
    8521.96 6541.26
    -2437.10 -9341.66
    1426.08 -4598.15
    -1313.60 -5460.46
    9619.09 -2907.44
    -7766.69 5561.20
    -4568.76 2373.66
    -2272.67 -4504.30
    4983.53 -862.03
    5568.69 -9504.63
    6419.29 8469.95
    -1603.52 5278.96
    4408.78 6946.22
    8715.10 3547.80
    -9124.10 -4804.25
    -7249.33 4678.44
    -7993.08 -7301.47
    575.58 -3353.11
    -8522.70 -1154.17
    2473.10 -4792.57
    9958.54 238.04
    -8444.98 9325.95
    843.17 4248.05
    2630.35 -7148.13
    2256.68 -1183.78
    7317.13 2459.62
    5282.64 -1486.13
    5415.26 1816.71
    -1536.22 -3157.64
    -7477.61 -7977.69
    8544.21 4791.74
    3900.90 8284.43
    -2542.39 -4359.05
    -5409.07 2841.65
    -4427.36 -3985.43
    -4214.52 -5845.58
    -8817.80 3190.17
    7442.54 2332.91
    -3749.04 8651.16
    7151.33 -9193.55
    8399.79 7886.28
    -4746.44 -5734.53
    9154.36 -3546.40
    -3792.21 -7164.91
    -1565.25 -7721.91
    -3795.18 -7493.79
    
    
  • 相关阅读:
    英雄
    Sublime text 2/3 中 Package Control 的安装与使用方法
    python安装
    flex与C# Socket通信
    ActionScript接收socket服务器发送来的数据
    什么是Socket,为什么要用Socket
    Response.End(); 用HttpContext.Current.ApplicationInstance.CompleteRequest 代替
    探索C#之6.0语法糖剖析
    行为树(Behavior Tree)实践(1)– 基本概念
    浅谈层次化的AI架构
  • 原文地址:https://www.cnblogs.com/lifehappy/p/12696554.html
Copyright © 2011-2022 走看看