圆排列问题Word格式.docx
《圆排列问题Word格式.docx》由会员分享,可在线阅读,更多相关《圆排列问题Word格式.docx(10页珍藏版)》请在冰豆网上搜索。
compute用于计算当前圆排列的长度
变量min用于记录当前最小圆排列的长度;
数组r表示当前圆排列;
数组x则记录当前圆排列中各圆的圆心横坐标
算法中约定在当前圆排列中排在第一个的圆的横坐标为0
在递归算法中bracktrack中
当i>
n时
算法搜索至叶结点
得到新的圆方案
此时算法调用compute计算当前圆排列的长度
适时更新当前最优值
当i<
当前扩展结点位于排列树的第I-1层
此时算法选择下一个要排列的圆
并计算相应的下界函数
在满足下界约束的结点处
以深度优先的方法递归地对相应子树搜索
对于不满足结点的结点
则剪去相应的子树
三、程序
/*********************************
*程序名
版本:
*开发日期:
2005.10.24
*简要说明:
将N个大小不等的圆排进一矩形中
且各圆与矩形框底边相切
从所有
排列中找出最小长度的圆排列
***********************************/
#include"
math.h"
//预编译
iostream.h"
#defineN100//宏定义
voidSwap(float&
a,float&
b)//交换两个值
{
intt;
t=a;
a=b;
b=t;
}
classCircle
{
friendfloatCirclePerm(int,float*);
//定义友好类
public:
//定义公共子函数
floatCenter(intt);
voidCompute(void);
voidBacktrack(intt);
//定义变量
floatmin,//当前最优值
*x,//当前圆排列圆心横坐标
*r;
//当前圆排列
intn;
//待排列的圆的个数
};
/*******************************************
*函数名:
Circle:
:
Center
*传入值:
当前要排列圆的半径
*输出值:
当前所选圆的圆心横坐标
*简要说明:
计算当前所选圆的圆心横坐标
*******************************************/
floatCircle:
Center(intt)//计算当前所选圆的圆心横坐标
floattemp=0;
for(intj=1;
j<
t;
j++)
{
floatvaluex=x[j]+2*sqrt(r[t]*r[j]);
cout<
<
"
shuchuv"
<
endl;
valuex<
if(valuex>
temp)temp=valuex;
}
returntemp;
Circle:
Compute
当前搜索圆的横坐标和半径
当前搜索圆排列的长度
计算当前圆排列的长度
voidCircle:
Compute(void)//计算当前圆排列的长度
floatlow=0,high=0;
for(inti=1;
i<
=n;
i++)
if(x[i]-r[i]<
low)low=x[i]-r[i];
if(x[i]+r[i]>
low)high=x[i]+r[i];
}
if(high-low<
min)min=high-low;
endl<
shumin"
;
min<
Backtrack
1
当前圆排列的最优值
查找当前最优值
Backtrack(intt)//查找当前最优值
{
if(t>
n)Compute();
else
for(intj=t;
=n;
Swap(r[t],r[j]);
r[t]<
r[j]<
floatcenterx=Center(t);
if(centerx+r[t]+r[1]<
min)
x[t]=centerx;
Backtrack(t+1);
jiaohuaner:
"
;
r[t]<
r[j]<
CirclePerm
n
a
当前找到的圆的最小长度
计算找到的最小圆排列长度
floatCirclePerm(intn,float*a)//计算找到的最小圆排列长度
CircleX;
X.n=n;
X.r=a;
X.min=100000;
float*x=newfloat[n+1];
//申请空间
X.x=x;
X.Backtrack
(1);
delete[]x;
//释放空间
returnX.min;
main
无
圆排列的最小长度
调用各个子程序
输出所有
排列中找出最小长度
voidmain(void)
//定义变量
floata[N],k;
intm,n;
yuangeshu:
cin>
>
n;
for(m=1;
m<
m++)
a[m];
k=CirclePerm(n,a);
shuchuzuixiaomin"
k<
endl;
四、与圆排列随机化算法的比较
解圆排列问题的一个随机化算法如下.
voidCircle_search(int*x)
random_perm(x);
found=true;
while(found){
found=false;
for(inti=1;
i<
=n;
i++)
for(intj=1;
j<
j++)
if(swap(x[i],x[j])reduceslength){
swap(x[i],x[j]);
其中,random_perm(x)产生x的一个随机排列
定义圆排列类
classCircle{
friendfloatCirclePerm(int,float*);
//返回找到的最小圆排列长度
private:
voidCenter(void);
//计算当前所有的圆在当前圆排列中圆心的横坐标
floatCompute(void);
//计算当前圆排列的长度
voidShuffle(void);
//随机洗牌算法
voidCircleSearch(void);
//解圆排列随机算法
floatmin,//当前最优值
result,//最优值
*x,//当前圆排列圆心横坐标
*r;
//当前圆排列
intn;
//等排列圆的个数
随机洗牌
Shuffle(void)
staticRandomNumberrnd;
for(inti=0;
iintj=rnd.Random(n-i)+i;
Swap(r[i],r[j]);
解圆排列随机算法
CircleSearch(void)
{Shuffle();
Center();
min=Compute();
boolfound=true;
ifor(intj=0;
jSwap(r[i],r[j]);
floatlength=Compute();
if(lengthmin=length;
elseSwap(r[i],r[j]);
}
返回找到的最小圆排列长度
floatCirclePerm(intn,float*a)
{CircleX;
X.n=n;
X.r=a;
float*x=newfloat[n];
iX.x=x;
X.CircleSearch();
X.result=X.min;
for(i=1;
iX.min){
delete[]x;
returnX.result;
五、算法效率比较
设循环次数为k;
圆排列随机化算法函数Center(void)计算时间需O(n2);
函数Circle:
CircleSearch(void)计算时间需O(n4);
整个算法时间复杂度O(Kn4)
圆排列问题的回溯算法在最坏情况下时间复杂度为O((n+1)!
)