Description:
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外,以上所有数据皆为正整数)
Input
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
Output
仅一行,是一个正整数S(若无解则S = 0)。
Sample Input
100 2
Sample Output
68
#include <iostream>
using namespace std;
int n, mm;
int ans = 0xffffff;
void dfs(int m, int sums, int sumv, int h, int r){
if(m == 0){
if(sumv == n && ans > sums)//不多余
ans = sums;
return;
}
if(2 * (n - sumv) / r + sums >= ans) // 整数型的是否有问题
return;
for(int i = h - 1; i >= m; i --){
for(int j = r - 1; j >= m; j --){
if(mm == m) sums = j * j;
dfs(m - 1, sums + i * j * 2, sumv + i * j * j, i, j);
}
}
}
int main(){
cin >> n >> mm;
dfs(mm, 0, 0, 10000, 100);
if(ans == 0xffffff) ans = 0;
cout << ans << endl;
return 0;
}
***这一题的主要思路是搜索与剪枝。我也是在借鉴了其他大佬的思路后才做出来的。
首先,通过分析题目中的“除Q外,所有数据均为整数”,可以得出,我们可以以1为步长进行枚举。当体积最大及N为10000时,半径r最大为100(当高度取最小值1时),高度h最大值为10000(当半径取最小值1时)。这样就确定对半径r和高度h枚举的上界了。至于下界,我们设蛋糕从顶至底分别是第1层至第M层(注意,与题目中规定的层的顺序相反。后面会发现这样相反的顺序更加方便),第i层的最小半径是i,因为从第i层向上到第1层,每层半径至少减少1,故得出这样的结果。同理,第i层最小高度为i。
有了代码搜索的上下界,就可以进行搜索。搜索过程需要剪枝。剪枝的方法有很多。第一种,当蛋糕摆到第i层时,剩下的层摆放所需的最小面积加上已经摆放的蛋糕的面积已经大于了当前最佳的面积;或者剩下层蛋糕所需的最小体积加上已摆放的体积大于了总体积。这种情况可以直接跳过,进入下一个搜索。第二种,利用数学推论,当摆到第I层时,剩下的体积摆成一个圆柱体的情况是表面积最好的情况。如果在这种条件下表面积之和仍小于当前最佳表面积,则可以直接跳过。这种方法我看的大佬的,具体如下:
/** * 2*r*h=S * r*r*h=V * => V*2/r = S * S + sumS >= best => return; */