圆排列问题

问题描述

圆排列问题:给定n个圆的半径序列,将它们放到矩形框中,各圆与矩形底边相切,求具有最小排列长度的圆排列

解析

圆排列问题的解空间是一棵排列树。按照回溯法搜索排列树的算法框架,设开始时a=[r1,r2,……rn]是所给的n个元的半径,则相应的排列树由a[1:n]的所有排列构成。
在这里插入图片描述如图,对于圆排列的问题,相邻的两个圆之间不一定会相切,如上方的第二个图。
如果有一个无限大的圆,那么这个矩形的长度就是这个圆的直径,如下图。
在这里插入图片描述调用递归函数,如果搜索到达叶子节点,生成这种排列顺序并计算长度,否则,搜索下个排列的圆。找出所有序列中长度最短的序列输出

设计

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
 
const int N=4;
double minlen=10000,x[N],r[N];//分别为最小圆排列长度,每个圆心横坐标,每个圆半径
double minr[N];//最小圆排列的半径顺序
 

void compute()
{
	double low=0,high=0;
	for(int i=1;i<N;i++)
	{
		if(x[i]-r[i]<low)
			low=x[i]-r[i];
		if(x[i]+r[i]>high)
			high=x[i]+r[i];
	}
	if(high-low<minlen)
	{
		minlen=high-low;
		for(int i=1;i<N;++i)
			minr[i]=r[i];
	}
}
double get_location(int t)//求圆心坐标
{
	double tmp=0;
	for(int j=1;j<t;++j)
	{
		double xvalue=x[j]+2.0*sqrt(r[t]*r[j]);
		if(xvalue>tmp)
			tmp=xvalue;
	}
	return tmp;
}
void backtrack(int t)
{
	if(t==N)
	{
		compute();
	}
	else
	{
		for(int j=t;j<N;j++)
		{
			swap(r[t],r[j]);
			double get_locationx=get_location(t);
			if(get_locationx+r[t]+r[1]<minlen)
			{
				x[t]=get_locationx;
				backtrack(t+1);
			}
			swap(r[t],r[j]);
		}
	}
}
int main()
{
	r[1]=2,r[2]=5,r[3]=4;
	
	for(int i=1;i<N;++i)
		cout<<"r"<<i<<"="<<r[i]<<' ';
	cout<<endl;
	backtrack(1);
	cout<<"矩阵长度:"<<minlen<<endl;
	cout<<"圆排列的顺序对应的半径分别为:";
	for(int i=1;i<N;++i)
		cout<<minr[i]<<' ';
	cout<<endl;
	return 0;
}

复杂度

T(n)=O(n^n)

github

https://github.com/1651928813/Pepsi_juice

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值