UVa OJ 10012

1、这道题的难点就在于“圆”,圆会相切,圆有大有小,所以要考虑各种情况。

2、用回溯法,每次添加一个新圆的时候,这个新圆可能与前面任一个圆重叠,所以要全部扫描一遍,求出位于最右边的圆心位置,存入b数组。

3、还要小心两端,每次添加新圆的时候,还要考虑是否和最左边的板重叠,而在计算最右边的板的位置的时候,要注意任何一个圆都可能与之相切。

#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
double ans;
int vis[10],m;
double a[10],b[10];
int c[10];
void dfs(int depth,int num){
    if(depth==m-1){
       double temp=0;
       for(int i=0;i<m;i++){
          if(a[c[i]]+b[i]>temp)
              temp=a[c[i]]+b[i];
       }
       if(temp<ans) ans=temp;
       return;
    }
    for(int i=0;i<m;i++)
       if(!vis[i]){
           vis[i]=1;
           double max=0;
           for(int j=0;j<=depth;j++){
               if(2*sqrt(a[i]*a[c[j]])+b[j]>max)
                   max=2*sqrt(a[i]*a[c[j]])+b[j];
           }
           if(a[i]>max) max=a[i];
           b[depth+1]=max;
           c[depth+1]=i;
           dfs(depth+1,i);
           vis[i]=0;
       }
    return;
}
int main(){
    int n;
    scanf("%d",&n);
    while(n--){
       scanf("%d",&m);
       ans=0;
       for(int i=0;i<m;i++){
          scanf("%lf",&a[i]);
          ans+=2*a[i];
       }
       memset(vis,0,sizeof(vis));
       for(int i=0;i<m;i++){
          vis[i]=1;
          b[0]=a[i];
          c[0]=i;
          dfs(0,i);
          vis[i]=0;
       }
       printf("%.3lf\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值