• NOJ 1118 玻璃球 【深蓝】[状态压缩DP]


    玻璃球 【深蓝】

    时间限制(普通/Java) : 10000 MS/ 30000 MS 运行内存限制 : 65536 KByte
    总提交 : 57            测试通过 : 11

    比赛描述

    玩过玻璃球游戏吗?sed同学小学没有毕业之前玩过,他常常用一个直径为d的圆柱管来装玻璃球,已知每个玻璃球是半径为 r1, r2, . . . , rn的球体,他当时一直有一个疑问:装这些玻璃球最少需要多长的圆柱管。现请你帮他解决这个问题。

    假设玻璃球半径充分大,以至于管中不存在三个可以同时相互接触的玻璃球。给定这样的限制,表示玻璃球将总以这样的方式装入:他们的中心点位于含导管旋转轴的2维平面上。

    输入

    输入包含多个测试例。每个测试例包括两行。每个测试例的第一行包含一个整数n (1 ≤ n ≤ 15) ,表示sed持有玻璃球的数目,还有一个浮点值d (2.0 ≤ d ≤ 1000.0) ,表示管子直径。两值以空格隔开。每个测试例的第二行包含n个由空格分隔的浮点数r1 r2 . . . rn(1.0 ≤ ri ≤ d/2) ,为sed玻璃球的半径。一个空白行分隔所以输入测试例。一行“0 0”表示输入结束,无需处理此例。

    输出

    对于每个输入测试例,打印管子的最短长度,结果取整。(四舍五入取整)

    样例输入

    2 98.1789
    42.8602 28.7622
    3 747.702
    339.687 191.953 330.811
    0 0

    样例输出

    138
    1628

    最终长度等于第一个球的半径 + 最后一个球的半径 + 中间相邻的球产生的高度。

    又是一道状态压缩的题目,dp[status][i]表示的是在选择玻璃球已经放入圆柱管的情况下,最上面的球是第i个球的最小长度

    状态转移方程 d[status][i] = d[status ^ (1 << i)][j] – d[j] +d[i] +height(i,j),其中 i 存在于在状态status中,j不存在于status中,height(i,j)相邻着放所产生的长度。

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    
    using namespace std;
    double d;
    int n;
    double r[20];
    
    double calheight(int i, int j)
    {
        double l = r[i] + r[j];
        double a = d - l;
        return sqrt(l*l - a*a);
    }
    
    double dp[1 << 16 |1][16]; //状态status下  i在最上面的最小值
    //dp[status][j]=dp[status ^ (1 << j)][i] - r[i] + cal(i,j) + r[j] ;
    
    bool read()
    {
        scanf("%d%lf", &n, &d);
        if(n == 0 && d == 0) return false;
        for(int i = 0; i < n; i++)
            scanf("%lf", &r[i]);
        return true;
    }
    
    int solve()
    {
        memset(dp, 0, sizeof(dp));
        for(int s = 0; s < (1 << n); s++)
        {
            for(int i = 0; i < n; i++)
            {
                if(s & (1<<i)) continue;
                if(s)
                    dp[s ^ (1<<i)][i] = 1000000000;
                else
                    dp[s ^ (1<<i)][i] = r[i] + r[i];
                for(int j = 0; j < n; j++)
                {
                    if(s & (1<<j))
                    {
                        dp[s ^ (1 << i)][i] = min(dp[s ^ (1<<i)][i], dp[s][j] - r[j] + r[i] + calheight(i,j));
                    }
                }
            }
        }
        double ans = 1000000000;
        for(int i = 0; i < n; i ++)
        {
            ans =min(ans, dp[((1 << n) - 1)][i]);
        }
        printf("%.0f
    ", (ans));
    
    }
    
    int main()
    {
        while(read())
        {
            solve();
        }
        return 0;
    }
    如果有错误,请指出,谢谢
  • 相关阅读:
    leetcode231 2的幂 leetcode342 4的幂 leetcode326 3的幂
    leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence
    leetcode64. Minimum Path Sum
    leetcode 20 括号匹配
    算法题待做
    leetcode 121. Best Time to Buy and Sell Stock 、122.Best Time to Buy and Sell Stock II 、309. Best Time to Buy and Sell Stock with Cooldown 、714. Best Time to Buy and Sell Stock with Transaction Fee
    rand7生成rand10,rand1生成rand6,rand2生成rand5(包含了rand2生成rand3)
    依图
    leetcode 1.Two Sum 、167. Two Sum II
    从分类,排序,top-k多个方面对推荐算法稳定性的评价
  • 原文地址:https://www.cnblogs.com/Alruddy/p/7124272.html
Copyright © 2020-2023  润新知