• poj1190


    题意:一个由多个圆柱体摞起来形成的蛋糕,要求上边的圆柱的半径和高都比下边的圆柱大。给定圆柱的体积,问除去下表面之外的圆柱面积最小是多少?

    分析:深度优先搜索。由最底层的蛋糕向上逐层搜索,每次迭代则蛋糕向上一层。所以搜索深度确定,为蛋糕的层数。

    与通常的深度优先搜索不同的是,本题的每个搜索状态由两个量来标明:半径和高。因此向下一个状态迭代时需要用一个二重循环来枚举接下来状态的半径和高。

    可见状态空间极大。需要三个剪枝方可通过本题。

    我们首先要了解,位于蛋糕顶端的x层的最小体积是:1^3+2^3+3^3+...+x^3

    最小面积是:2*(1^2+2^2+3^2+...+x^2)

    即从顶层向下半径依次取1~x,高依次取1~x。

    三个剪枝是:

    1.总体积减去蛋糕当前层以下的层的总体积是否小于上面的层所能构成的最小体积。如果小于则返回。

    2.已算得的答案(最小面积)减去蛋糕当前层以下的层的总面积是否小于上面的层所能构成的最小面积。如果小于则返回。

    3.设剩余总体积为总体积减去蛋糕下面的层的总体积,剩余总面积是当前已得最优解减去蛋糕当前层以下的层的总面积。设ri为每层的半径,hi为每层的高度。蛋糕上面层的总面积是对2*ri*hi求和。总体积ri*ri*hi求和。剩余总体积*2再除以当前层的半径必须小于剩余总面积,否则返回。(2×sigma(ri*ri*hi)/rk > sigma(2*ri*hi) i=1~k)之所以左边大于右边是因为rk>ri  对于i<k。

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    #define MAX_LAYER_NUM 25
    #define INF 0x3f3f3f3f
    
    int layer_num;
    int total_volume;
    int min_vol[MAX_LAYER_NUM];
    int min_area[MAX_LAYER_NUM];
    int ans;
    
    void init()
    {
        min_area[0] = min_vol[0] = 0;
        for (int i = 1; i <= 20; i++)
        {
            min_vol[i] = min_vol[i - 1] + i * i * i;
            min_area[i] = min_area[i - 1] + 2 * i * i;
        }
    }
    
    void DFS(int r_limit, int h_limit, int layer, int area, int volume)
    {
        if (layer == 0)
        {
            if (volume != total_volume)
                return;
            ans = min(ans, area);
            return;
        }
        if (total_volume - volume < min_vol[layer])
            return;
        if (ans - area < min_area[layer])
            return;
        if (layer < layer_num && area + 2 * (total_volume - volume) / r_limit > ans)
            return;
        for (int i = r_limit; i >= layer; i--)
        {
            if (layer == layer_num)
            {
                area = i * i;
            }
            int max_h = (total_volume - min_vol[layer - 1] - volume) / (i * i);
            for (int j = min(max_h, h_limit); j >= layer; j--)
            {
                DFS(i - 1, j - 1, layer - 1, area + 2 * i * j, volume + i * i * j);
            }
        }
    }
    
    int main()
    {
        scanf("%d%d", &total_volume, &layer_num);
        ans = INF;
        init();
        DFS((int)sqrt(total_volume), total_volume, layer_num, 0, 0);
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    金蝶报错事项
    ROS的脚本多拨
    zabbix4.0 相关的拓扑图及centos的虚拟配置
    ros开启快速转发模式
    linux 配置 l2tp-client
    linux 系统管理 实战技巧
    Flunetd 用于统一日志记录层的开源数据收集器
    在Centos7 更改Docker默认镜像和容器的位置
    Supervisor: 进程控制系统
    如何用正确的姿势查看 主机系统的CPU信息
  • 原文地址:https://www.cnblogs.com/rainydays/p/3523162.html
Copyright © 2020-2023  润新知