状压dp 处理有相邻顺序的或者有序的状态压缩问题

Globulous Gumdrops
My Tags (Edit) Cancel - Seperate tags with commas.

Source : 2008 Stanford Programming Contest
Time limit : 1 sec Memory limit : 64 M
Submitted : 170, Accepted : 92
Description

Gwen just bought a bag of gumdrops! However, she does not like carrying gumdrops in plastic bags; instead, she wants to pack her gumdrops in a cylindrical tube of diameter d. Given that each of her gumdrops are perfect spheres of radii r1, r2, … , rn, find the shortest length tube Gwen can use to store her gumdrops.

You should assume that the gumdrop radii are sufficiently large that no three gumdrops can be simultaneously in contact with each other while fitting in the tube. Given this restriction, it may be helpful to realize that the gumdrops will always be packed in such a way that their centers lie on a single two-dimensional plane containing the axis of rotation of the tube.

Input

The input file will contain multiple test cases. Each test case will consist of two lines. The first line of each test case contains an integer n (1 <= n <= 15) indicating the number of gumdrops Gloria has, and a floating point value d (2.0 <= d <= 1000.0) indicating the diameter of the cylindrical tube, separated by a space. The second line of each test case contains a sequence of n space-separated floating point numbers, r1 r2 … rn (1.0 <= ri <= d/2) are the radii of the gum drops in Gloria’s bag. A blank line separates input test cases. A single line with the numbers “0 0” marks the end of input; do not process this case.

Output

For each input test case, print the length of the shortest tube, rounded to the nearest integer.

Sample Input

2 98.1789
42.8602 28.7622
3 747.702
339.687 191.953 330.811
0 0
Sample Output

138
1628

此类问题 两维,第一维就是 状态,第二维是最后一个放的物品,然后推公式就很好写了

题意:给你n个球和筒的直径,问堆完所有球的最小高度

画个图推推公式就好

有一个小问题是 double 必须输入 %f 还有 就是 0x3f3f3f3f 只能用于整数数组 不能用于小数数组。
转移方程 dp[st|(1<

#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>
using namespace std;
double dp[(1<<15)+100][16];
double r[20];
const double inf = 1000000.0;
double d;

double ji(int x,int y)
{
    double rr= sqrt((double)(r[x]+r[y])*(r[x]+r[y])-(double)(d-r[x]-r[y])*(d-r[x]-r[y]));
   return rr;
}

int main()
{
    int n;
    while(~scanf("%d%lf",&n,&d))
    {
        if(n==0&&d==0.0) break;
    for(int i=0;i<n;i++)
    {
        scanf("%lf",&r[i]);
    }
    int END = (1<<n);
    for(int i=0;i<END;i++)
        for(int j=0;j<n;j++)
        dp[i][j]=inf;

    for(int i=0;i<n;i++)
    {
        dp[(1<<i)][i]=2*r[i];
    }
    for(int i=1;i<END;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(dp[i][j]!=inf)
            {
                for(int k=0;k<n;k++)
                {
                    if((i&(1<<k))==0)
                    {
                        dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]-r[j]+ji(j,k)+r[k]);
                    }
                }
            }
        }
    }
    double minn=inf;
    for(int i=0;i<n;i++)
    {
        minn=min(minn,dp[END-1][i]);
    }
    printf("%d\n",int(minn+0.5));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值