大作业——圆排列问题

本文探讨了如何解决圆排列问题,即在矩形框内按一定条件排列给定半径的圆,使得排列长度最小。通过解析算法,设计了回溯法求解第n个圆的横坐标,并提供了详细的代码实现。分析表明,算法的时间复杂度为O(n!)。
摘要由CSDN通过智能技术生成

1,问题

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

2,解析

主要利用回溯法来解决该问题。
r[n]: 记录每个圆的半径
x[n]: 记录每个圆的横坐标
minlen: 圆排列最小长度
函数 center(n): 求第n个圆的横坐标
函数 compute(): 计算当前r[n]的排列的长度
backtrack(t): t<n, 遍历排列树t层,更新minlen.

在这里插入图片描述

3,设计

double center(int t)//得到每个圆的圆心坐标
{
double temp=0;
for(int j=1;j<t;++j)
{
double xvalue=x[j]+2.0*sqrt(r[t]*r[j]);
if(xvalue>temp)
temp=xvalue;
}
return temp;
}
在这里插入图片描述
因为存在这样的情况,就不能直接根据排在其前面那个圆来求出其横坐标,事实上每一个排在所求的圆的前面的圆都有可能和其相切。

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)
bestr[i]=r[i];
}
}
在这里插入图片描述

因为存在这样的情况,所以不能直接根据圆序列的第一个圆和最后一个圆横坐标差+两个圆的半径来求长度。

void backtrack(int t)
{
if(t==N)
{
compute();
}
else
{
for(int j=t;j<N;++j)
{
swap(r[t],r[j]);
double centerx=center(t);
if(centerx+r[t]+r[1]<minlen)
{
x[t]=centerx;
backtrack(t+1);
}
swap(r[t],r[j]);
}
}
}

利用递归来遍历序列树的每一层,利用循环来遍历每一层的每一种情况,最终得到最短长度。

4,分析

算法时间复杂度:O(n!)

5,源码

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;

const int N = 4;
double minlen = 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值