zoukankan      html  css  js  c++  java
  • 凸包问题

    (1)问题描述

    用分分治法编写一个求解凸包问题的算法,并测试算法的正确性。
    【注:凸包问题】给定平面上n个点,从中找出一个最小点集,使该点集所组成的凸多边形包围所有的n个点。

    (2)问题分析

    将n个点分为两部分,则每一部分可以形成一个凸包,重复分下去最后将多个凸包合并即可得到n个点的凸包。

    (3)算法设计

    将n个点按横坐标从小到大排列,则x1,xn必定属于最小点集,x1,xn连线将n个点分成两部分,下面只需找各自的凸包即可。以找上凸包为例,在上半部分的点中找到距离x1,xn连线最远的点,将该点与x1,xn相连则可将上半部分分为3块,则找到上凸包的问题又转化为找出另外两个凸包的问题。上凸包和下凸包要分开处理。递归结束的条件是连线的上方(上凸包)/下方(下凸包)没有点。重复此操作即可得到最后整个的凸包。

    (4)算法实现

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    #include<fstream>
    #include<sstream>
    
    using namespace std;
    
    struct Point {
    	double x;
    	double y;
    };
    inline bool Compx(const Point &p1, const Point &p2)
    {
    	return p1.x < p2.x;
    }
    /*
    函数:求点p在以p1和p2决定直线的上侧还是下侧
    返回值:上侧:>0    下侧:<0    在直线上:=0
    */
    inline double Line(const Point &p1, const Point &p2, const Point &p)
    {
    	return (p1.y - p2.y) * p.x + (p2.x - p1.x) * p.y + (p1.x * p2.y - p1.y * p2.x);
    }
    /*
    函数:求点p到以p1和p2决定直线的距离
    */
    double Dist(const Point &p1, const Point &p2, const Point &p)
    {
    	double A = p1.y - p2.y;
    	double B = p2.x - p1.x;
    	double C = p1.x * p2.y - p1.y * p2.x;
    	return abs(A*p.x + B * p.y + C) / sqrt(A*A + B * B);
    }
    /*
    函数:求解直线p1p2上点集的上包
    参数:v:直线p1p2上方的点集 vo:上包点集
    */
    void UpHull(const vector<Point> &v, vector<Point> &vo, const Point &p1, const Point &p2)
    {
    	if (v.size() == 0)
    		return;
    	if (v.size() == 1) {
    		vo.push_back(v[0]);
    		return;
    	}
    
    	double d = 0;
    	int k;
    	for (size_t i = 0; i < v.size(); ++i) {
    		double t = Dist(p1, p2, v[i]);
    		if (t > d) {
    			d = t;
    			k = i;
    		}
    	}
    	vo.push_back(v[k]);
    	vector<Point> vl;
    	vector<Point> vr;
    	for (size_t i = 0; i < v.size(); ++i) {
    		if (Line(p1, v[k], v[i]) > 0)
    			vl.push_back(v[i]);
    		else if (Line(v[k], p2, v[i]) > 0)
    			vr.push_back(v[i]);
    	}
    
    	UpHull(vl, vo, p1, v[k]);
    	UpHull(vr, vo, v[k], p2);
    }
    /*
    函数:求解直线p1p2下点集的下包
    参数:v:直线p1p2下的点集 vo:下包点集
    */
    void DownHull(const vector<Point> &v, vector<Point> &vo, const Point &p1, const Point &p2)
    {
    	if (v.size() == 0)
    		return;
    	if (v.size() == 1) {
    		vo.push_back(v[0]);
    		return;
    	}
    
    	double d = 0;
    	int k;
    	for (size_t i = 0; i < v.size(); ++i) {
    		double t = Dist(p1, p2, v[i]);
    		if (t > d) {
    			d = t;
    			k = i;
    		}
    	}
    	vo.push_back(v[k]);
    	vector<Point> vl;
    	vector<Point> vr;
    	for (size_t i = 0; i < v.size(); ++i) {
    		if (Line(p1, v[k], v[i]) < 0)
    			vl.push_back(v[i]);
    		else if (Line(v[k], p2, v[i]) < 0)
    			vr.push_back(v[i]);
    	}
    
    	DownHull(vl, vo, p1, v[k]);
    	DownHull(vr, vo, v[k], p2);
    }
    /*
    函数:求解点集v的凸包
    */
    void ConvexHull(vector<Point> &v, vector<Point> &vo)
    {
    	sort(v.begin(), v.end(), Compx);
    	vo.push_back(v[0]);
    	vo.push_back(v[v.size() - 1]);
    	vector<Point> vu;
    	vector<Point> vd;
    	for (size_t i = 1; i < v.size() - 1; ++i) {
    		if (Line(v[0], v[v.size() - 1], v[i]) >= 0)
    			vu.push_back(v[i]);
    		else if (Line(v[0], v[v.size() - 1], v[i]) < 0)
    			vd.push_back(v[i]);
    	}
    	UpHull(vu, vo, v[0], v[v.size() - 1]);
    	DownHull(vd, vo, v[0], v[v.size() - 1]);
    }
    int main()
    {
    	vector<Point> v;
    	ifstream input("Points.txt", ifstream::in);
    	string line;
    	Point p;
    	while (getline(input, line)) {
    		stringstream liness(line);
    		liness >> p.x >> p.y;
    		v.push_back(p);
    	}
    	vector<Point> vo;
    	ConvexHull(v, vo);
    	for (auto p : vo)
    		cout << "<" << p.x << "," << p.y << ">" << endl;
    	system("pause");
    	return 0; 
    }
    
    

    输入文件Points.txt:

    0 0
    1 5
    2 2
    3 -1
    4 5
    5 -3
    6 0
    

    (5)运行结果

  • 相关阅读:
    8.CNN应用于手写字识别
    8.优化器
    6.正则化
    5.Dropout
    4.交叉熵
    3.Minst数据集分类
    2.非线性回归
    1.线性回归
    110. Balanced Binary Tree
    106. Construct Binary Tree from Inorder and Postorder Traversal
  • 原文地址:https://www.cnblogs.com/Frank-Hong/p/13335562.html
Copyright © 2011-2022 走看看