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

    定义1:平面上的点集,如果以该集合中的任意两点P和Q为端点构成的线段属于该集合,就称该集合是凸的。

    定义2:一个点集S的凸包是包含S的最小凸集合。

    定理:任意包含n > 2个点的集合S的凸包是以S中的某些点为顶点的凸多边形。(如果所有点是共线的,多边形退化为线段)

    因此,直观看来,任意的凸多边形都是凸集合。

    凸包问题是为一个包含n个点的集合构造一个凸包。

    根据上面的定理设计了一个基于线性规划的算法来判断能否构造凸包。算法描述如下:

    两点确定一条直线(线段),因此,在n个点的集合中的点i和j可以确定一条直线,当且仅当其余n-2个点位于该直线上或者是该直线同一侧时,点i和j的连线才是凸包的一部分边界。直线的方程:f=ax+by-c=0;其中a=y2-y1;b=x1-x2;c=x1*y2-y1*x2,将剩余的点的坐标带入该方程,如果都是f >= 0或者都是f <= 0,说明(x1,y1),(x2,y2)构成的线段是凸包的边界。代码如下:

    #include <iostream>
    #include <complex>
    #include <cstdlib>
    using namespace std;
    void fun(complex<int> *point, int n);
    int main()
    {
    	complex<int> point[5] = { complex<int>(0,0),complex<int>(2,0),complex<int>(2,2),complex<int>(0,2),complex<int>(1,1) };
    	fun(point, 5);
    	system("pause");
    }
    void fun(complex<int> *point, int n)
    {
    	int count1,count2;
    	int k;
    	int temp;
    	for (int i = 0; i < n; i++)
    	{
    		for (int j = i + 1; j < n; j++)		//遍历所有可能的线段
    		{
    			count1 = 0;
    			count2 = 0;
    			for (k = 0; k < n; k++)
    			{
    				if (k != i  && k != j)
    				{
                        //计算公式
    					temp = point[i].real()*point[j].imag() + 
    						point[k].real()*point[i].imag() + 
    						point[j].real()*point[k].imag() - 
    						point[k].real()*point[j].imag() - 
    						point[j].real()*point[i].imag() - 
    						point[i].real()*point[k].imag();
    					if (temp > 0)
    					{
    						count1++;
    					}
    					if (0 == temp)
    					{
    						count2++;
    					}
    				}
    			}
    			if (n - 2 == count2)    //在一条直线上的时候
    			{
    				cout << "凸多边形退化为线段,两个端点分别是:" <<
    					point[i] << "和" << point[j] << endl;
    				return;
    			}
    			if ((count1 == n - 2) || (0 == count1))    //不在一条直线上
    			{
    				cout << "凸多边形其中一条边的两个端点是:" <<
    					point[i] << "和" << point[j] << endl;
    			}
    		}
    	}
    	cout << "凸包构造完毕!" << endl;
    }

    上述算法的时间复杂度是O(n³),很不理想。有待改进。

  • 相关阅读:
    学习ESLint的规则配置,ESLint语法检测配置说明
    慎用Request.Params获取参数值
    [C#.NET 拾遗补漏]04:你必须知道的反射
    .NET Web应用中为什么要使用async/await异步编程
    Asp.Net Core Web Api 使用 Swagger 生成 api 说明文档
    网页打印尺寸设置
    Object 标签遮挡 Div 显示
    C# 之 批量插入数据到 SQLServer 中
    PrintDocument打印、预览、打印机设置和打印属性的方法
    JS 之 阻止事件冒泡,阻止默认事件,event.stopPropagation()和event.preventDefault(),return false的区别
  • 原文地址:https://www.cnblogs.com/zy666/p/10504299.html
Copyright © 2011-2022 走看看