【NOI1999】生日蛋糕

来源:互联网 发布:股份公司股东人数 知乎 编辑:程序博客网 时间:2024/05/01 23:18

【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 <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <stack>#include <map>#include <vector>#include <queue>#define INF 2147483647#define LL long longusing 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

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

0 0
原创粉丝点击