ACWing168生日蛋糕(搜索剪枝)

题目传送门:https://www.acwing.com/problem/content/170/
题目大意:
给定蛋糕的体积和层数,要再此蛋糕的表面抹奶油,要想奶油成本最低,如何建这个M层的蛋糕。
分析:
此题是一个典型的搜索题,因为找不到递推式,或者贪心,或者分治等算法的思路。当走投无路时,试试搜索吧。那么搜可按蛋糕的底层开始,逐层搜索到顶层,到了顶层m层再维护一个表面积最大。但是这个搜索状态可多了,如何剪枝,去掉不可能的解就是非常重要的了。可以从以下几个方面考虑(截图于ACwing上VMice的题解,全文题解网址链接:https://www.acwing.com/solution/AcWing/content/1500/):
在这里插入图片描述那么附上代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 20+6;
const int INF = 1000000000;
int n,m,mins[MAXN],minv[MAXN],ans = INF,r[MAXN],h[MAXN];
void dfs(int dep,int s,int v)//dep表示正在处理第dep层,s表示已经有的表面积,v表示已经由的体积。
{
	 if(dep == 0) {
	 	if(v == n) ans = min(ans, s);//当到了目标状态时维护最小值。
	 }	 
	 else{
	 	for(int ri = min((int)(sqrt(n-v)) , r[dep+1] - 1); ri>= dep; ri --){
	 		for(int hi = min((int)((n-v)/(1.0*(ri * ri))),h[dep+1] - 1); hi>= dep; hi--){
	 			r[dep] = ri;
	 			h[dep] = hi;
	 			//当已经产生的表面积加上还没有做成的层数中最少的表面积都比ans大则此分支不可能有最优解,剪去。 
				 if(s + mins[dep] > ans) continue;
				 //当已经产生的体积加上还没有做成的层数中最小的体积都比n要大,则此分支不可行,剪掉。 
				 if(v + minv[dep] > n)continue; 
				 //数学分析进行最优性剪枝(此剪枝比较难想到。)
				 if(s + 2.0*(n-v)/ri > ans) continue;
				 if(dep == m) s = ri * ri;//当在最底层时加上底面的圆面积。
				 dfs(dep - 1, s + 2 * ri * hi, v + ri * ri * hi) ;
				 if(dep == m) s = 0;
	 		}
	 	}
	 } 
} 
int main(){
	cin >> n >> m;
	//从上往下用最小的半径和最小的高度来作为从顶端到第i层的最小表面积和最小体积。 
	//供后面可行性剪枝用。 
	for(int i = 1;i<= m; i++){
		mins[i] = mins[i - 1] + 2 * i * i;
		minv[i] = minv[i - 1] + i * i * i; 
	}
	r[ m+1 ] = h[m+1] = INF;
	dfs(m , 0 , 0); 
	if(ans == INF) cout << 0;
	else cout << ans ; 
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值