package 蓝桥杯;
import java.util.Scanner;
public class VO深搜_生日蛋糕 {
static int N,M;//面积和层数
static int minArea=1<<30;//最优表面积
static int area=0;//正在搭建中的蛋糕的表面积
static int[] minlastarea,minlastv,minlasthr;
public static void main(String[] args) {
Scanner reader=new Scanner(System.in);
N=reader.nextInt();
M=reader.nextInt();
//提前算好还有last层没搭建需要的最小面积和体积,提供给剪枝使用
minlastarea=new int[M+1];
minlastv=new int[M+1];
minlasthr=new int[M+1];
for(int last=1;last<=M;last++) {
minlastarea[last]=2*last*last+minlastarea[last-1];
minlastv[last]=last*last*last+minlastv[last-1];
}
if(minlastv[M]>N)System.out.println(0);
else {
int maxR=(int) (Math.sqrt(1.*(N - minlastv[M-1]) / M) + 1);
int maxH=(N-minlastv[M-1])/(M*M)+1;;
dfs(N,M,maxR,maxH);
if(minArea==1<<30)
System.out.println("0");
else
System.out.println(minArea);
}
}
static int maxlastv(int n,int r,int h) {
int v=0;
//在还要搭n层蛋糕,蛋糕底层最大半径r,最高高度h的情况下,能凑出来的最大体积
int maxH=h,maxR=r;
for(int last=n;last>0;last--){
v+=maxH*maxR*maxR;
maxH--;
maxR--;
}
return v;
}
static void dfs(int v,int n,int r,int h) {
//递归状态的终止条件
if(n==0) {
if(v!=0) {return;}//如果体积没有达到要求
else {
minArea=Math.min(minArea, area);
{return;}
}
}
if(v<=0)
{return;}
//1、(最优性剪枝)搭建过程中发现已建好的面积area已经超过目前求得的最优表面积minArea,或者预见到搭完后面积一定超过目前最优表面积,则停止搭建
if(area>=minArea||area+minlastarea[n]>=minArea) {return;}
//2、(可行性剪枝)搭建过程中预见到再往上搭,高度已经无法安排,或者半径已经无法安排,则停止搭建
if(n>h||n>r) {return;}
//3、(可行性剪枝)搭建过程中发现还没搭的那些层的体积,已经会超过还缺的体积,则停止搭建
if(minlastv[n]>v) {return;}
//4、(可行性剪枝)搭建过程中发现还没搭的那些层的体积,最大也到不了还缺的体积,则停止搭建
if(maxlastv(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;
}
}
}
}
生日蛋糕 剪枝细节深搜DFS实现(Java)
最新推荐文章于 2021-05-25 04:34:51 发布