hoj 1061 排列树问题
Problem C:排列树问题
Time Limit:5000MS Memory Limit:65536K
Total Submit:55 Accepted:3
Description
试设计一个用回溯法搜索排列空间树的函数。该函数的参数包括结点可行性判定函数和上界函数等必要的函数,并将此函数用于解圆排列问题。
圆排列问题描述如下:给定n 个大小不等的圆c1 , c2 ,..., cn ,现要将这n 个圆排进一个矩形框中,且要求各圆与矩形框的底边相切。圆排列问题要求从n 个圆的所有排列中找出有最小长度的圆排列。例如,当n=3,且所给的3 个圆的半径分别为1,1,2 时,这3 个圆的最小长度的圆排列是1,2,1,其最小长度为2 + 4*sqr(2)。
编程任务:
对于给定的n(n≤≡10)个圆,编程计算最小长度排列。
Input
输入由多组测试数据组成。
每组测试数据输入的第一行是1 个正整数n,表示有n个圆。第2行有n个正数,分别表示n个圆的半径。
Output
对应每组输入,输出的每行是计算出的最小长度,保留3 位小数。
Sample Input
3 1 1 2
Sample Output
7.657
[Submit] [Go Back] [Status] [Clarify]
#include <iostream>
#include <cmath>
#define MAX 13
using namespace std;
int nn;
class Circle
{
private:
double mmin, //??????????
x[MAX], //????????????????????
r[MAX]; //??????????
int n; //??????????????
public:
Circle()
{
mmin=100000000;
}
void Set();
void Swap(int i,int j);
double Center(int t);
void Computer();
void Backtrack(int t);
double GetMmin();
};
void Circle::Set()
{
int i;
n=nn;
for(i=1;i<=n;i++)
{
scanf("%lf",&r[i]);
x[i]=0;
}
}
void Circle::Swap(int i,int j)
{
double temp;
temp=r[i];
r[i]=r[j];
r[j]=temp;
}
double Circle::Center(int t) //????????????????????????????
{
int j;
double temp=0,valuex;
for(j=1;j<t;j++)
{
valuex=x[j]+2.0*sqrt(r[t]*r[j]);
if(valuex>temp)
temp=valuex;
}
return temp;
}
void Circle::Computer() //??????????????????
{
double low=0,high=0;
int i;
for(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<mmin)
mmin=high-low;
}
void Circle::Backtrack(int t)
{
int j;
double centerx;
if(t>n)
Computer();
else
{
for(j=t;j<=n;j++)
{
Swap(t,j);
centerx=Center(t);
if(centerx+r[t]+r[1]<mmin)
{
x[t]=centerx;
Backtrack(t+1);
}
Swap(t,j);
}
}
}
double Circle::GetMmin()
{
return mmin;
}
/*double Circle::CirclePerm(int n,double *a)
{
Circle X;
X.n=n;
X.r=a;
X.mmin=1000000000;
double *x=new double[n+1];
X.x=x;
X.Backtrack(1);
delete [] x;
return X.mmin;
}*/
int main()
{
while(cin>>nn)
{
Circle X;
X.Set();
X.Backtrack(1);
printf("%0.3lf\n",X.GetMmin());
}
return 0;
}
#include <cmath>
#define MAX 13
using namespace std;
int nn;
class Circle
{
private:
double mmin, //??????????
x[MAX], //????????????????????
r[MAX]; //??????????
int n; //??????????????
public:
Circle()
{
mmin=100000000;
}
void Set();
void Swap(int i,int j);
double Center(int t);
void Computer();
void Backtrack(int t);
double GetMmin();
};
void Circle::Set()
{
int i;
n=nn;
for(i=1;i<=n;i++)
{
scanf("%lf",&r[i]);
x[i]=0;
}
}
void Circle::Swap(int i,int j)
{
double temp;
temp=r[i];
r[i]=r[j];
r[j]=temp;
}
double Circle::Center(int t) //????????????????????????????
{
int j;
double temp=0,valuex;
for(j=1;j<t;j++)
{
valuex=x[j]+2.0*sqrt(r[t]*r[j]);
if(valuex>temp)
temp=valuex;
}
return temp;
}
void Circle::Computer() //??????????????????
{
double low=0,high=0;
int i;
for(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<mmin)
mmin=high-low;
}
void Circle::Backtrack(int t)
{
int j;
double centerx;
if(t>n)
Computer();
else
{
for(j=t;j<=n;j++)
{
Swap(t,j);
centerx=Center(t);
if(centerx+r[t]+r[1]<mmin)
{
x[t]=centerx;
Backtrack(t+1);
}
Swap(t,j);
}
}
}
double Circle::GetMmin()
{
return mmin;
}
/*double Circle::CirclePerm(int n,double *a)
{
Circle X;
X.n=n;
X.r=a;
X.mmin=1000000000;
double *x=new double[n+1];
X.x=x;
X.Backtrack(1);
delete [] x;
return X.mmin;
}*/
int main()
{
while(cin>>nn)
{
Circle X;
X.Set();
X.Backtrack(1);
printf("%0.3lf\n",X.GetMmin());
}
return 0;
}