UVa 10012 - How Big Is It?

/*
    暴力枚举,模拟放入圆。 半径为R1、R2的两个圆相切,通过勾股定理推出,两圆心的水平距离为 2sqrt(R1*R2)
    注意到对一些特殊情况处理,如例子 4 1000.0  1.0 1.0 1.0
    最坏时间复杂度为 8!,其实可以优化成 8!/2, 因为排序1、2、3 和 排序3、2、1求出来的值是相等的。
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAX = 8+2;
int m;
double r[MAX]; //半径
double min_len;

double get_len()
{
    double c[MAX]; //圆心坐标,以箱子左边为原点
    double max_c;
    double len = 0;
    for(int i=0; i<m; i++) {
        max_c = r[i];
        for(int j=0; j<i; j++) {//分别求出第i个圆和前i-1个圆相切时i圆心的坐标,取最大的i圆心坐标
            double k = 2 * sqrt(r[i]*r[j]); // k 为第i个圆心和第j个圆心的水平距离
            if(k+c[j] > max_c) max_c = k+c[j];
        }
        c[i] = max_c;
        if(c[i] + r[i] > len) len = c[i] + r[i];
    }
    return len;
}

int main(void) {
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    int n;
    scanf("%d", &n);
    while(n--) {
        scanf("%d", &m);
        if(m<=0) continue;
        for(int i=0; i<m; i++) {
            scanf("%lf", &r[i]);
        }
        min_len = 10e8;
        sort(r, r+m);
        do{
            double temp = get_len();
            if(temp < min_len) min_len = temp;
        }while(next_permutation(r, r+m));
        printf("%.3lf\n", min_len);

    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值