1. 程式人生 > >How Big Is It?行吧,學不會的dp

How Big Is It?行吧,學不會的dp

8024: How Big Is It?

時間限制: 1 Sec  記憶體限制: 128 MB 提交: 50  解決: 13 [提交] [狀態] [討論版] [命題人:admin]

題目描述

Ian's going to California, and he has to pack his things, including his collection of cirles. Given a set of cirles, your program must find the smallest rectangular box in which they fit. All cirles must touch the bottom of the box. The figure below shows an acceptable packing for a set of cirles (although this may not be the optimal packing for these partiular cirles). Note that in an ideal packing, each cirle should touch at least one other cirle (but you probably figured that out).

輸入

The first line of input contains a single positive decimal integer n, n < 50. This indicates the number of lines which follow. The subsequent n lines each contain a series of numbers separated by spaces. The first number on each of these lines is a positive integer m, m < 8, which indicates how many other numbers appear on that line. The next m numbers on the line are the radii of the cirles which must be packed in a single box. These numbers need not be integers.

輸出

For each data line of input, excluding the first line of input containing n, your program must output the size of the smallest rectangle which an pack the cirles. Each case should be output on a separate line by itself, with three places after the decimal point. Do not output leading zeroes unless the number is less than 1, e.g. 0.543.

樣例輸入

3
3 2.0 1.0 2.0
4 2.0 2.0 2.0 2.0
3 2.0 1.0 4.0

樣例輸出

9.657
16.000
12.657

來源/分類

給你一堆圓,問排成一排的最小長度是多少,,

顯然,如果圓直徑相差不大的話,直接排序就好,然而如果相差很大,

那小圓就可以放在大圓的空隙裡,計算的話就很不好想

如果相差不大的話,稍微推一下可以得到兩圓之間的水平距離是sqrt((r+R)^2-(R-r)^2),然後化簡下得到2*sqrt(R*r)

這樣,每個圓和都和之前能放的最遠的圓相切時恰好使得長度最小,那麼當前狀態由之前的所有狀態轉移過來

太菜了,這題隊友給講的

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
double p[50],pos[50];
double Dist(double x,double y){
    return 2*sqrt(x*y);
}
int main(){
    int t,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%lf",&p[i]);
        double ans = 1e10;
        sort(p,p+n);///sort下,因為next函式
        do{
            double tans = p[0]*2;///初始值為第一個圓的直徑
            pos[0] = p[0];///第一個圓的位置
            for(int i=1;i<n;i++){
                double dis = p[i];
                for(int j=i-1;j+1;j--)///找擺放最遠的圓
                    dis = max(dis,pos[j]+Dist(p[i],p[j]));
                pos[i] = dis;///更新當前圓位置
                tans = max(tans,dis+p[i]);
///本次排列的最小長度是最大的當前圓位置+當前圓的半徑
            }
            ans = min(ans,tans);///更新最小的答案
        }while(next_permutation(p,p+n));///列舉每一種排列
        printf("%.3f\n",ans);
    }
    return 0;
}