UVa 10012 - How Big Is It?

来源:互联网 发布:数据接口程序 编辑:程序博客网 时间:2024/06/06 03:23

以为很简单,十分钟敲了一个全排列回溯,结果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;}