【NOI1999】生日蛋糕

【NOI1999】生日蛋糕

Description

7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。

设从下往上数第i(1<=i<=M)层蛋糕是半径为Ri,高度为Hi的圆柱。当i时,要求Ri>Ri+1且Hi>Hi+1。

由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。

令Q= Sπ

请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。

(除Q外,以上所有数据皆为正整数)

Input

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

Output

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

Sample Input

100

2

Sample Output

68

Hint

附:圆柱公式

体积V=πR^2H

侧面积A’=2πRH

底面积A=πR^2

Source

[NOI1999]

数学,搜索,剪枝

Solution

对于这道题的面积,显然只有最底一层的表面积需要计算,其他层只需要考虑侧面积

首先考虑到直接搜索会很慢,需要考虑到剪枝,我写了两个剪枝:

可行性剪枝(对体积):当前体积加上下一层最小的体积也比n大,那么该种方案不可行;

最优性剪枝(对面积):1、当前面积加上下一层的最小侧面积比记录的ans大,那么该种方案定然不是最优的;2、如果剩余体积对应的下一层侧面积加上当前面积大于等于ans,该方案不是最优的(必须是大于等于因为下一层的半径取不到当前的r)

剪完枝后就可以枚举下一层面积以及下一层高度,递归搜索即可

为了方便,我预处理出了每一层的最小体积以及最小面积存于a、b数组中

Code

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 2147483647
#define LL long long
using namespace std;

int n, m, a[30], b[30], ans = INF;

inline void search(int v, int s, int p, int r, int h) {//v-->now V, s-->now S, p-->number, r-->now R, h-->now H
  if (p == 0) {
    if (v == n && s < ans) ans = s;
    return ;
  }
  //possible
  if (v + b[p - 1] > n) return ;
  //better
  if (s + a[p - 1] > ans) return ;
  if (2 * (n - v) / r + s>= ans) return ;
  //search the next level's height
  for (int i = r - 1; i >= p; --i) {//for R
    if (p == m) s = i * i;
    int hh = min(h - 1, (n - v - b[p - 1]) / (i * i));
    for (int j = hh; j >= p; --j) search(v + i * i * j, s + 2 * i * j, p - 1, i, j);//for H
  }
}

int main() {
  freopen("1221.in", "r", stdin);
  freopen("1221.out", "w", stdout);
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= 20; ++i) a[i] = a[i - 1] + 2 * i * i, b[i] = b[i - 1] + i * i * i;
  search(0, 0, m, n + 1, n + 1);
  if (ans >= INF) printf("0\n");
  else printf("%d\n", ans);
  return 0;
}

Summary

注意判断不存在答案的情况

你可能感兴趣的:(搜索)