您的位置:首页 > 其它

UVa 10012 - How Big Is It?

2012-09-12 18:26 459 查看
以为很简单,十分钟敲了一个全排列回溯,结果WA了。想了半天,才想到可能存在两个半径很大的圆相切,中间夹着很多小的圆(这样单纯的全排列只判断相邻两圆的话就可能出现圆圆相交的情况),这样就需要加一个圆心坐标和一个原点记录位置来做特判,令当前放置的圆与前面所有的圆相切求出最大的据原点的距离(这样就可以保证排除圆圆相交的情况),再加上前面的距离即为放置这个新的圆的位置坐标。

代码如下:



#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
int vis[8], num;
double a[8], b[8], d[8], _max;
void check(int cur) // 求新圆放置的位置
{
d[cur] = b[cur];
double dis1, dis2, dis;
for(int i = cur - 1; i >= 0; i--)
{
dis1 = b[i] + b[cur];
dis2 = b[i] - b[cur];
dis = d[i] + sqrt(dis1 * dis1 - dis2 * dis2);
if(dis > d[cur])
d[cur] = dis;
}
}
void dfs(int cur, double sum) // dfs,全排列
{
if(sum > _max)
return ;
if(cur == num)
{
double l = b[0];
sum += b[cur - 1];
for(int i = 0; i < num - 1; i++)
if(d[i] + b[i] > sum)
sum = d[i] + b[i];
for(int i = 1; i < num; i++)
if(b[i] - d[i] > l)
l = b[i] - d[i];
sum += l;
if(sum < _max)
_max = sum;
return ;
}
for(int i = 0; i < num; i++)
if(!vis[i])
{
vis[i] = 1;
b[cur] = a[i];
check(cur);
dfs(cur + 1, d[cur]);
vis[i] = 0;
}
}
int main()
{
#ifdef test
freopen("sample.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
memset(vis, 0, sizeof(vis));
while(n--)
{
_max = 0x7FFFFFFF;
scanf("%d", &num);
for(int i = 0; i < num; i++)
scanf("%lf", &a[i]);
for(int i = 0; i < num; i++)
{
vis[i] = 1;
d[0] = 0;
b[0] = a[i];
dfs(1, 0);
vis[i] = 0;
}
printf("%.3lf\n", _max);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: