• NOI题库192 生日蛋糕


    192:生日蛋糕

    总时间限制:

    5000ms

    内存限制:

    65536kB

    描述

    7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为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外,以上所有数据皆为正整数)

    输入

    有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。

    输出

    仅一行,是一个正整数S(若无解则S = 0)。

    样例输入

    100

    2

    样例输出

    68

    提示

    圆柱公式
    体积V = πR2H
    侧面积A' = 2πRH
    底面积A = πR2

    来源

    Noi 99

    【思路】

      搜索+剪枝。

      依次搜索每一层的高度与半径。三个剪枝策略如下:

        //这里用到的三个剪枝
        //sums + mins[deep]> best 表示以前的到的deep + 1层到 m 层的表面积加上从顶层到deep层的最小表面积如果都大于了已经得到的best,那么1到deep层是无论半径和高度取何值都是无效的
        //sumv + minv[deep] > n同理
        // 2 * (n - sumv) / r + sums >= best 这是该题的精髓,如果没有的话会造成超时,是为了把sumv和sums联系起来,原因如下:
        // 假设能够得到best时(为什么这样假设呢,因为如果得不到的话那么就已经被第一个剪枝滤去了,所以在第三个剪枝验证时表示已经通过了第一个剪枝的要求),
        // n - sumv = h[1] * r[1] * r[1] + ... + h[deep] * r[deep] * r[deep] < h[1] * r[1] * r + ... + h[deep] * r[deep] * r (因为r是deep + 1层的半径)
        //其中h[1]...h[deep]表示在函数的形参情况下,1到deep层应该取得h值,r[1]同理
        // 两边同时处以r 再乘以2得 2 * (n - sumv) / r < 2 * (h[1] * r[1] + ... + h[deep] * r[deep]) 
        // 2 * (n - sumv) / r < best - sums
        // 2 * (n - sumv) / r + sums < best 成立 ,则可得剪枝条件
    

    【代码】

     1 #include<iostream>
     2 #include<cmath>
     3 using namespace std;
     4 
     5 using namespace std;
     6 
     7 const int maxn = 20+5;
     8 const int INF=1e9;
     9 
    10 int minv[maxn],mins[maxn];
    11 int n,m,ans;
    12 
    13 void init() {
    14     for(int i=1;i<=m;i++) {
    15         minv[i]=minv[i-1]+i*i*i;
    16         mins[i]=mins[i-1]+2*i*i;
    17     }
    18 }
    19 
    20 void dfs(int dep,int v,int r,int h,int S) {
    21     if(!dep) {
    22         if(v==n&&S<ans) ans=S;
    23         return ;
    24     }
    25     if(S+mins[dep]>ans || v+minv[dep]>n ||(2 * (n - v) / r + S >= ans) ) return ;
    26     
    27     for(int nowr=r-1;nowr>=dep;nowr--) {
    28         if(dep==m) S=nowr*nowr;
    29         int maxh=min(h-1,n-v-minv[dep-1]/nowr*nowr);
    30         for(int nowh=maxh;nowh>=dep;nowh--)
    31         {
    32             dfs(dep-1,v+nowr*nowr*nowh,nowr,nowh,S+2*nowr*nowh);
    33         }
    34     }
    35 }
    36 
    37 int main() {
    38     cin>>n>>m;
    39     init();
    40     ans=INF;
    41     dfs(m,0,sqrt(n),n+1,0);  //当只有一层时得到 R H 上限 
    42     if(ans==INF) cout<<0;
    43     else cout<<ans;
    44     return 0;
    45 }
  • 相关阅读:
    java错误分析之junit测试错误(实验一)
    oracle逐步学习总结之oracle分页查询(基础三)
    OracleServer总结进阶之系统分析(进阶完结)
    QMS 的趨勢概述
    Python 類別 class 的繼承 Inheritance
    Python 面向導向語言 Object Oriented Programming Language
    Python 參考資源
    Dynamics 365-CRM又报看不懂的错误了
    Dynamics 365-为什么查到的Record的Id是Guid初始值
    Dynamics 365-如何下载新版本的Tools
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4936099.html
Copyright © 2020-2023  润新知