生日蛋糕 剪枝细节深搜DFS实现(Java)

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;
			}
		}
	}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值