【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 <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 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

注意判斷不存在答案的情況

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章