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设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。
由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
令Q = Sπ
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
(除Q外,以上所有数据皆为正整数)
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
Output仅一行,是一个正整数S(若无解则S = 0)。
Sample Input100 2Sample Output
68Hint
圆柱公式
体积V = πR 2H
侧面积A' = 2πRH
底面积A = πR 2
体积V = πR 2H
侧面积A' = 2πRH
底面积A = πR 2
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int minv[30],minb[30]; //由题目可知,每一层的半径与高度是逐渐递减的,且最小是少1
int n,m,ans; //所以提前把每一层的体积与表面积算出来
void dfs(int sum,int v,int dep,int h,int r) //sum 表面涂的面积 v是蛋糕体积 dep是第几层 h是高度 r是半径
{
if(v>n)return ; //如果堆蛋糕的体积已经大于所给体积了,那么就无法再向上搭建了
if(dep==0) //如果搭建完成了且此时蛋糕刚好用完,判断此时的表面积是否是最优的
{
// printf("%d %d\n",v,sum);
if(v==n&&sum<ans)
{
ans=sum;
}
return;
}
// 如果现在的体积加上下一层所用的最小体积依然大于规定的体积,那就返回上一层
// 如果现在所求的表面积加上下一层的依然大于之前所求的的结果,则返回
// 如果剩余体积的测面积加上之前的大于之前求得的最优结果,返回上一层.
if(v+minv[dep-1]>n||sum+minb[dep-1]>ans|| (n-v)/r*2+sum>=ans)return;
for(int i=r-1;i>=dep;i--) //从大到小枚举,所求的结果一定是最优的
{
if(dep==m)sum=i*i; //到了最后一层的时候要算上顶部
int th=min(h-1,(n-v-minv[dep-1])/(i*i)); //找到这一层的最小高度
for(int j=th;j>=dep;j--)
{
dfs(sum+2*i*j,v+i*i*j,dep-1,j,i);
}
}
return;
}
int main()
{
for(int i=1;i<21;i++)
{
minv[i]=minv[i-1]+i*i*i;
minb[i]=minb[i-1]+i*i*2;
}
while(~scanf("%d%d",&n,&m))
{
ans=0x3f3f3f3f;
dfs(0,0,m,n+1,n+1);
if(ans==0x3f3f3f3f)
ans=0;
printf("%d\n",ans);
}
return 0;
}