Description
ncust要制作一个体积为 Nπ 的 M层生日蛋糕,每层都是一个圆柱体。
设从下往上数第 i 层蛋糕是半径为Ri ,高度为 Hi 的圆柱。当 i<M时,要求 Ri>R(i+1) 且Hi>H(i+1) 。由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积 Q最小。
令 Q=Sπ,请编程对给出的 N和 M ,找出蛋糕的制作方案(适当的 Ri和 Hi 的值),使 S最小。(除 Q 外,以上所有数据皆为正整数)
Input
第一行为 N,表示待制作的蛋糕的体积为 Nπ;
第二行为 M,表示蛋糕的层数为 M 。
Output
输出仅一行,一个整数S (若无解则 S=0 )。
Sample Input
100
2
Sample Output
68
More Info
附:圆柱相关公式:体积V=π(R^2)H ;侧面积S’=2πRH ;底面积S=π(R^2) 。
对于全部数据:1<=N<=10^4,1<=M<=20
问题求解
题目中很明显告诉我们可以直接在表面积和体积中省去pi。
dfs部分:
(1)明显看到这是一道dfs题,但是仅仅只是dfs的,时间是肯定不允许的额,因此需要剪枝操作。
(2)dfs部分我们可以逐层深度搜索,void dfs(int x, int r, int h, int s, int v) 其中x为层数,第x层的蛋糕高度为h,半径为r,表面积为s,体积为v。
(3)使用两个for循环枚举半径和高度。
剪枝操作:
(1)当前的奶油面积+之后的最小奶油面积>现在已求出的的最小奶油面积——return;
(2)当前的体积>n——return;
(3) 当前的体积+之后的最大体积<体积总数——return;
上代码
#include<stdio.h>
#include<math.h>
#define MIN 99999999999999
int n, m,mins = MIN;
void dfs(int x, int r, int h, int s, int v)
{
if (s > mins || v > n)
{
return;//当前的面积+之后的最小面积>现在已求出的的最小面积,return 当前的体积>n,return
}
if (x == m && v==n) //层数达到m并且体积达到v
{
if (s < mins)
mins = s;//要求面积s最小
return;
}
else
{
if (v + (h * r * r) * (m - x) <= n)
return;
//当前的体积 + 之后的最大体积 < 体积总数,return
}
for (int h1 = h -1; h1 >= m - x; h1--)//高度为整数 递减
{
for (int r1 = r - 1; r1 >= m - x; r1--) //半径为整数 递减
{
dfs(x + 1, r1, h1, s + 2 * r1 * h1, v + r1 * r1 * h1);
}
}
}
int main() {
scanf("%d%d", &n, &m);
for (int h = n / (m * m); h >= m; h--) //n>=m*m*h
{
for (int r = sqrt(n / m); r >= m; r--)//r*r*m<=n
//两个for循环遍历全部半径和高度
{
dfs(1, r, h, r * r + 2 * r * h, h * r * r);//第一层: 半径为r,高度为h,表面积pi*(r*r+2*r*h),体积pi*r*r*h 逐层搜索
}
}
if (mins == MIN)
{
printf("0");
}
else
{
printf("%d", mins);
}
}