此题大意:给定一定数量的圆,然后将其装在箱子里,求箱子最小的宽度
要求是:每个圆都必须与底部接触,同时每个圆必须与至少一个院邻接(这在程序中体现为相切) 。
注意点:就是打球非常大,而小球非常小。。
此题算法就是:暴力求解,加上一定的判断。
//
// main.cpp
// uva 10012 - How Big Is It?
//
// Created by XD on 15/8/8.
// Copyright (c) 2015年 XD. All rights reserved.
//
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
using namespace std ;
double x[10] ;
double last_1 ,last_2 ;
double radii[10] ;
int perm[10] ;
int n ;
double getAns()
{
double r1 , r2 ;
double x1 = 0.0 ;
for (int i = 0; i < n; i++) {
r2 = radii[perm[i]];
x[i] = 2 * r2 ;
int j = 0 ;
for (j = 0 ; j < i; j++) {
//这里是剪枝,去掉那些不可能相切的点,依据为:当前原点的坐标必须要大于他前一个圆的圆点的坐标。
if (x[j] + r2 < x[i-1]-radii[perm[i-1]]) {
continue ;
}
else{
break ;
}
}
for( ; j < i ; j++ )
{
x1 = x[j] ; r1 =radii[perm[j]] ;
x1 = r2 + pow(4 * r1 * r2, 0.5) - r1 + x1 ;
x[i]= x[i] >x1?x[i]:x1 ;
}
}
double tmax = -1 ;
for(int i = 0 ;i < n;i++)
{
tmax=tmax > x[i]?tmax:x[i] ;
}
return tmax ;
}
void solved()
{
// int temp[10] ;
for (int i =0 ; i < n; i++) {
perm[i] = i ;
}
double ans = 2147483646 ;
do{
double t_ans = getAns() ;
if (ans>t_ans) {
ans = t_ans ;
}
}while (next_permutation(perm, perm+n)) ;
printf("%.3lf\n" ,ans) ;
}
int main() {
int casenum ;
scanf("%d" ,&casenum) ;
while (casenum--) {
scanf("%d" , &n) ;
for (int i = 0 ; i < n ; i++) {
scanf("%lf" , &radii[i]) ;
}
solved() ;
}
return 0;
}