[uva] 10012 - How Big Is It?
【题目】http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=953
【题意】最多8个圆在同切一水平线,然后外相切,求其最小宽度。
【算法】简单几何
【题解】最多八个圆,所以全排列一遍,然后圆心从左到右依次相切,分别求出其宽度,最后选出最小。共50个Case 时间复杂度50*8*8!
【注意】注意左右两边的处理
【测试】
3
1 1
2 10 1
3 10 1 1
ans:
2.000
20.000
20.000
【代码】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
struct circle{
double x,r;
}c[10];
double ans;
void set_circle(int t){
double left=-c[0].r,right=c[0].r,max,rt;
int i,j;
c[0].x=0;
for(i=1;i<=t;i++){
c[i].x=0;
for(j=0;j<i;j++){
rt=2.0*sqrt(c[j].r*c[i].r)+c[j].x;
c[i].x=c[i].x>rt?c[i].x:rt;
left=(c[i].x-c[i].r)<left?(c[i].x-c[i].r):left;
right=(c[i].x+c[i].r)>right?(c[i].x+c[i].r):right;
}
}
if(ans==-1)ans=right-left;
else ans=ans<(right-left)?ans:(right-left);
}
void swap(int a,int b){
double t;
t=c[b].r;
c[b].r=c[a].r;
c[a].r=t;
}
void full_array(int s,int t){
if(s>=t){
set_circle(t);
return;
}
for(int i=s;i<=t;i++){
swap(s,i);
full_array(s+1,t);
swap(s,i);
}
}
int main(){
int T,n,i;
scanf("%d",&T);
while(T-->0){
scanf("%d",&n);
for(i=0;i<n;i++) scanf("%lf",&c[i].r);
ans=-1;
full_array(0,n-1);
printf("%.3f\n",ans);
}
return 0;
}