【题目描述】
Mr.W 要制作一个体积为 Nπ 的 M 层生日蛋糕,每层都是一个圆柱体。 设从下往上数第 i 蛋糕是半径为 Ri,高度为 Hi 的圆柱。当 i<M时,要求 Ri>Ri+1且 Hi>Hi+1。由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积 Q最小。 令 Q =Sπ ,请编程对给出的 N 和 M ,找出蛋糕的制作方案(适当的 Ri 和 Hi 的值),使 S 最小。
(除 Q 外,以上所有数据皆为正整数)
【输入格式】
第一行为 N ,表示待制作的蛋糕的体积为 Nπ;
第二行为 M ,表示蛋糕的层数为 M 。
【输出格式】
输出仅一行,一个整数 S(若无解则 S=0 )。
【样例输入】
100
2
【样例输出】
68
【附:圆柱相关公式:】
体积 V= π R 2 H \pi R^{2}H πR2H
侧面积 S ′ = 2 π R h S{}'=2\pi Rh S′=2πRh
底面积 S = π R 2 S=\pi R^{2} S=πR2
【数据范围与提示】
对于全部数据,1≤N≤10^4,1≤M≤20。
大致思路
ss[0]=0;vv[0]=0;
for(int i=1;i<=17;i++){
ss[i]=ss[i-1]+2*i*i;//面积
vv[i]=vv[i-1]+i*i*i;//体积
}
inline void dfs(int v,int s,int m,int r,int h){
for(int i=r-1;i>=m;i--){//枚举上一层的半径
if(m==mm)s=i*i;
for(int j=min((n-v-vv[m-1])/(i*i),h-1);j>=m;j--){//枚举上一层的高
dfs(v+i*i*j,s+2*i*j,m-1,i,j);
}
if(2*(n-v)/r+s>ans)return;//最重要的剪枝:当前的表面积+余下的侧面积>当前最优值
if(v+vv[m]>n)return;//体积超出
if(s+ss[m]>ans)return;//表面积超出
剪完枝就可以完美ac啦
#include<bits/stdc++.h>
using namespace std;
int n,mm,ans=1e9;
int ss[130],vv[130];//ss存储表面积,vv存储体积
inline void dfs(int v,int s,int m,int r,int h){
if(2*(n-v)/r+s>ans)return;//最重要的剪枝:当前的表面积+余下的侧面积>当前最优值
if(v+vv[m]>n)return;//体积超出
if(s+ss[m]>ans)return;//表面积超出
if(m==0){//v为已用体积,s为已有表面积,p为剩余层数,r为半径,h为高
if(v==n)ans=min(s,ans);//判断是否符合要求并得到更优解
return;
}
for(int i=r-1;i>=m;i--){//枚举上一层的半径
if(m==mm)s=i*i;
for(int j=min((n-v-vv[m-1])/(i*i),h-1);j>=m;j--){//枚举上一层的高
dfs(v+i*i*j,s+2*i*j,m-1,i,j);
}
}
}
int main(){
cin>>n>>mm;
ss[0]=0;vv[0]=0;
for(int i=1;i<=17;i++){
ss[i]=ss[i-1]+2*i*i;//第i层使用的最大表面积
vv[i]=vv[i-1]+i*i*i;//第i层使用的最大体积
}
dfs(0,0,mm,sqrt(n),sqrt(n));//r,h最大值为sqrt(n)
if(ans==1e9)cout<<0;
else cout<<ans;
return 0;
}