描述
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外,以上所有数据皆为正整数)
输入
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
输出
仅一行,是一个正整数S(若无解则S = 0)。
输入
100
2
输出
68
代码:
import java.util.Scanner;
public class Main {
public static int n,m,area=0,minarea=1<<30;
public static int[] minv=new int[30];
public static int[] mina=new int[30];
private static int maxvfornrh(int n,int r,int h){
int v=0;
for (int i = 0; i < n; i++) {
v+=(r-i)*(r-i)*(h-i);
}
return v;
}
private static void dfs(int v,int n,int r,int h){
if(n==0){
if(v!=0){
return; //不能搭建
}else{
minarea=Math.min(minarea, area);
}
}
if(v<=0){return;}
if(minv[n]>v) return;
if(area+mina[n]>=minarea)return;
if(h<n || r<n) return;
if(maxvfornrh(n,r,h)<v)return;
for (int rr = r; rr >=n; rr--) {
if(n==m){area=rr*rr;}
for(int hh=h;hh>=n;hh--){
area+=2*rr*hh;
dfs(v-rr*rr*hh,n-1,rr-1,hh-1);
area-=2*rr*hh;
}
}
}
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
n=Integer.parseInt(sc.nextLine());
m=Integer.parseInt(sc.nextLine());
minv[0]=0;mina[0]=0;
for(int i=1;i<=m;i++){
minv[i]=minv[i-1]+i*i*i;
mina[i]=mina[i-1]+2*i*i;
}
if(minv[m]>n){
System.out.println(0);
}else{
int maxh=(n-minv[m-1])/(m*m)+1;
int maxr=(int)(Math.sqrt((double)(n-minv[m-1])/m))+1;
area=0;
minarea=1<<30;
dfs(n,m,maxr,maxh);
if(minarea==1<<30){
System.out.println(0);
}else{
System.out.println(minarea);
}
}
}
}