最小凸多边形(凸包)

描述

给出平面上n个点的坐标,计算最远两点间的距离,以及包含所有点的最小凸多边形(凸包)

输入
第一行一个整数n,接下来是n行的实数对,表示n个点坐标。2<=n<=10000
n
x1 y1
x2 y2

xn yn

输出
输出2行,第一行是最远两点间的距离,结果保留四位小数。第二行是从P0开始,逆时针输出凸包的顶点号。

顶点号为0到n-1,由点的输入次序决定。

P0点表示最下方的点号,如果有多个点并列最下方,则P0为其中最左边的点号。

输入样例 1

9
200 400
300 400
300 300
400 300
400 400
500 400
500 200
350 200
200 200

输出样例 1
360.5551
8 6 5 0

这里用于sort排序的数组ord[],用的很巧妙。
凸包形成过程如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define eps 1e-8
using namespace std;
typedef struct
{
    double x, y;
} point;


point p[10005];
//用于排序的标号,并保存输入时的顺序标号 
int ord[10005];
int n;
//stack用于保存最小凸包的顶点序号 
int stack[10005];

double dist(point a,point b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

int check(point a,point b,point c){
    double k;
    k = a.x*b.y-a.y*b.x+b.x*c.y-b.y*c.x+c.x*a.y-c.y*a.x;
    if(k>eps)
        return 1;
    else if(k<-eps)
        return -1;
    else
        return 0;
}

bool cmp(int a,int b){//排序依据 
	int i;
	i=check(p[ord[0]],p[a],p[b]);
	if(i==0) return(dist(p[ord[0]],p[a])<dist(p[ord[0]],p[b]));
	else return i>0;
}

int main()
{
    cin >> n;
    int i, j,temp;
    for (i = 0; i < n;i++){
        cin >> p[i].x >> p[i].y;
        ord[i] = i;
    }
    int k = 0;
    for (i = 1; i < n;i++){
        if(p[i].y<p[k].y || (p[i].y==p[k].y && p[i].x<p[k].x))
            k = i;
    }
    swap(ord[0], ord[k]);
    
	//将所有点按与水平面夹角大小排序 
    sort(ord + 1, ord + n, cmp);
    
    stack[0] = ord[0];
    int top=0;
    for (i = 1; i < n;i++){
    	/*当点p[ord[i]]在线p[stack[top-1]],p[stack[top]]的右边时,链接不构成凸包.
		  所以舍去栈顶的点p[stack[top]],换成点p[ord[i]]。                    */ 
		while(top>0 && check(p[stack[top-1]],p[stack[top]],p[ord[i]])<=0)  top--;
        stack[++top] = ord[i];
    }
    
   
    double ans;
    for (i = 0; i <= top;i++){//求最长两点距离 
        for (j = i + 1; j <= top;j++){
            ans = max(dist(p[stack[i]], p[stack[j]]),ans);
        }
    }
    printf("%.4lf\n", ans);
    for (i = 0; i <= top; i++)
        cout << stack[i] << " ";
    return 0;
}

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在MATLAB中绘制多个连通区域的最小凸多边形,可以按照以下步骤进行: 1. 首先,使用图像处理的方法将图像转换为二值图像,即将连通区域中的像素值设置为1,其他非连通区域的像素值设置为0。 2. 接着,利用MATLAB内置函数regionprops来获取连通区域的属性,括每个连通区域的像素索引。 3. 对于每个连通区域,使用convhull函数来计算出最小凸多边形的顶点索引。convhull函数使用算法,将给定的点云集合转换为最小凸多边形的顶点索引。 4. 最后,使用plot函数将每个连通区域的最小凸多边形绘制出来。可以循环处理每个连通区域的顶点索引,将其连接成闭合的凸多边形。 下面是一个简单的示例代码: ```matlab % 假设已经有了一个二值图像bw_image,含了多个连通区域 % 获取连通区域属性 cc = bwconncomp(bw_image); props = regionprops(cc, 'PixelIdxList'); % 绘制每个连通区域的最小凸多边形 figure; hold on; for i = 1:cc.NumObjects pixelIdxList = props(i).PixelIdxList; [row, col] = ind2sub(size(bw_image), pixelIdxList); % 计算最小凸多边形的顶点索引 k = convhull(col, row); % 绘制最小凸多边形 plot(col(k), row(k), 'r'); end hold off; ``` 以上代码将绘制出每个连通区域的最小凸多边形,其中bw_image是一个二值图像,表示了多个连通区域。每个连通区域的最小凸多边形将用红色线条绘制出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值