【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
注意判斷不存在答案的情況