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 }
原文地址:https://www.cnblogs.com/lidaxin/p/4936099.html