#include <iostream>
#include <fstream>
#include <queue>
#include <cmath>
using namespace std;
const int INF = 100000;
const int MAX = 50;
float r[MAX]; //圆的半径
int n; //圆的个数
class Node
{
public:
int dep; //当前层
float len; //圆排列长度
float *x; //当前圆排列圆心坐标
float *r; //当前圆排列
Node(int d, float l)
{
x = new float[n+1];
r = new float[n+1];
dep = d;
len = l;
}
//计算当前所选择圆的圆心
float center(int t)
{
int j;
float temp = 0.0;
float valuex;
for(j=1; j<t; j++)
{
valuex = x[j] + 2.0*sqrt(r[j]*r[t]); //寻找当前层下最右边的圆心
if(valuex > temp)
temp = valuex;
}
return temp;
}
//计算当前圆排列的长度
float getLen(int t)
{
int i;
float low = 0.0; //圆位于原点右侧
float high = 0.0;
for(i=1; i<=t; i++)
{
if(x[i] - r[i] < low) //寻找最左边的坐标,当圆位于原点左侧时才会更新
low = x[i]-r[i];
if(x[i] + r[i] > high) //寻找最右边的坐标
high = x[i]+r[i];
}
return high - low;
}
//圆排列长度小的先出队列
bool operator < (const Node &node) const
{
return len > node.len;
}
};
float search()
{
priority_queue<Node> q;
Node enode(0, 0);
copy(r, r+n+1, enode.r);
for(int j=1; j<=n; j++)
enode.x[j] = 0;
float best = INF;
do
{
if(enode.dep == n-1) //只有一个儿子结点
{
enode.x[n] = enode.center(n);
enode.len = enode.getLen(n);
if(enode.len < best)
{
best = enode.len;
break;
}
}
else
{
for(int i=enode.dep+1; i<=n; i++)
{
Node now(enode.dep+1, enode.len);
copy(enode.x, enode.x+n+1, now.x);
copy(enode.r, enode.r+n+1, now.r);
now.r[now.dep] = enode.r[i];
now.r[i] = enode.r[now.dep];
now.len = now.getLen(now.dep);
now.x[now.dep] = now.center(now.dep);
if(now.len < best)
q.push(now);
}
}
if(q.empty())
break;
else
{
enode = q.top();
q.pop();
}
}while(enode.len < best);
return best;
}
int main()
{
ifstream fin("圆排列.txt");
cout << "输入圆的个数:";
fin >> n; cout << n;
cout << "\n输入各圆的半径:\n";
int i, j;
for(i=1; i<=n; i++)
{
fin >> r[i];
cout << r[i] << " ";
}
cout << "\n圆排列最小长度为:" << search();
cout << endl;
cout << endl;
fin.close();
return 0;
}
圆排列问题
最新推荐文章于 2024-04-22 14:00:36 发布