• poj1190 生日蛋糕


    题意:

    要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。 由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。 令Q = Sπ 请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。 (除Q外,以上所有数据皆为正整数)

    思路:

    深搜(枚举每一层的高度和半径)+剪枝

    最优性剪枝:

    搭建过程中预见到搭完后面积一定会超过目前最优表面积,则停止搭建。

    可行性剪枝:

    1.搭建过程中预见到再往上搭,高度已经无法安排,或者半径已经无法安排,则停止搭建。

    2.搭建过程中发现还没搭的那些层的体积,最大也到不了还缺的体积,则停止搭建。(之前搭得太小)

    3.搭建过程中发现还没搭的那些层的体积,一定会超过还缺的体积,则停止搭建。(之前搭得太大)

    实现:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #define INF 0x3f3f3f3f
     5 using namespace std;
     6 int n, m;
     7 int min_now = INF;
     8 int minV[25];
     9 int minA[25];
    10 
    11 int cal2(int a)
    12 {
    13     return a * a;
    14 }
    15 
    16 int cal3(int a)
    17 {
    18     return a * a * a;
    19 }
    20 
    21 int maxV(int r, int h, int rem)
    22 {
    23     int ans = 0;
    24     for (int i = 0; i < rem; i++)
    25     {
    26         ans += r * r * h;
    27         r--, h--;
    28     }
    29     return ans;
    30 }
    31 
    32 void dfs(int cur, int v, int r, int h, int s)
    33 {
    34     if (s + minA[cur] >= min_now)  //最优性剪枝 
    35         return;
    36     if (r - 1 < m - cur || h - 1 < m - cur) //可行性剪枝1(之后无法安排)
    37         return;
    38     if (maxV(r - 1, h - 1, m - cur) < v) //可行性剪枝2(之前搭的太小)
    39         return;
    40     if (v < minV[cur]) //可行性剪枝3(之前搭得太大)
    41         return;
    42     if (cur == m)
    43     {
    44         if (v == 0)
    45         {
    46             if (s < min_now)
    47             {
    48                 min_now = s;
    49             }
    50         }
    51         return;
    52     }
    53     for (int i = h - 1; i >= 1; i--) // 枚举高度
    54     {
    55         for (int j = r - 1; j >= 1; j--) // 枚举半径
    56         {
    57             dfs(cur + 1, v - j * j * i, j, i, s + 2 * j * i);
    58         }
    59     }
    60 }
    61 
    62 int main()
    63 {
    64     cin >> n >> m;
    65     minV[0] = (1 + m) * m / 2;
    66     minV[0] = minV[0] * minV[0];
    67     minA[0] = m * (m + 1) * (2 * m + 1) / 3;
    68     for (int i = 1; i < m; i++)
    69     {
    70         minV[i] = minV[i - 1] - cal3(m - i + 1);
    71         minA[i] = minA[i - 1] - 2 * cal2(m - i + 1);
    72     }
    73     for (int i = sqrt(n) + 1; i >= m; i--)
    74     {
    75         for (int j = n / i / i; j >= m; j--)
    76         {
    77             dfs(1, n - i * i * j, i, j, i * i + 2 * i * j);
    78         }
    79     }
    80     if (min_now == INF)
    81         puts("0");
    82     else
    83         printf("%d
    ", min_now);
    84     return 0;
    85 }
  • 相关阅读:
    Javascript创建对象的学习和使用
    Javascript正则表达式的初步学习
    jQuery/javascript实现全选全不选
    jQuery/javascript实现网页注册的表单验证
    jQuery的简单入门练习
    jQuery实现左移右移
    jQuery/javascript实现简单网页计算器
    MySql的基本操作以及以后开发经常使用的常用指令
    Javascript实现计数器,定时警告和停止
    jQuery实现Checkbox中项目开发全选全不选的使用
  • 原文地址:https://www.cnblogs.com/wangyiming/p/6347170.html
Copyright © 2020-2023  润新知