POJ1190 生日蛋糕 + 深搜总结

题意:原谅我的懒

分析:

搜索即可。

基本思路:枚举每层的半径和高,dfs中传5个参数,当前的层,现有表面积,现有体积,当前层下一层的高度和半径。

剪枝:

1.从下往上搜索,减小搜索树。

2.枚举高度和半径时,倒序枚举,减小搜索树。

3.上下界,详见代码。

4.最优性剪枝:预处理1-dep层的最小体积和表面积,进行剪枝。

5.最优性剪枝(不好想):用体积和表面积的关系剪枝。

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

const int inf = 0x3fffffff;
int n,m,ans=inf,vv[25],ss[25];

void dfs(int dep, int s, int v, int h, int r) {
	if(!dep) {if(v == n) ans = min(ans, s+r*r); return;}
	if(v+vv[dep] > n || s+ss[dep] >= ans || s+2*(n-v)/r+r*r >= ans) return;
	for(int i = min(r-1, (int)sqrt((double)(n-v)/dep)); i >= dep; i--)
	for(int j = min(h-1, (n-v)/(i*i)); j >= dep; j--)
		dfs(dep-1, s+2*i*j+(dep==m?0:r*r-i*i), v+i*i*j, j, i);
}

int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i++) vv[i] = vv[i-1]+i*i*i, ss[i] = ss[i-1]+3*i*i-(i-1)*(i-1);
	dfs(m, 0, 0, inf, inf);
	printf("%d", ans == inf ? 0 : ans);
	return 0;
}
做了十几道深搜题了,来总结一下:

1.基本思路是怎么表示状态,可以传参,或用全局数组。

2.枚举的上下界剪枝,比如一些显然不可能的(参照上面的上下界剪枝),还有常见的比如放东西,放到空的里面都是一样的,就直接枚举到第一个空的停下即可。

3.避免重复搜索,如用vis数组判重,“木棍”中某长度的搜索失败不再尝试其他相同长度的等。

4.搜索顺序剪枝,一般都是为了减小搜索树,常用的如倒序,排序等。

5.答案很小或给定范围时,可以考虑用迭代加深。

6.当一个决策成功时,可能其他决策就显然不对了(贪心剪枝),如拦截导弹,如果能够用以前的系统拦截,则不需要新建一个系统。

7.可行性剪枝,如“木棍”,是总和约数再进行搜索和最长木棍搜索失败,直接返回。

8.最优性剪枝,见上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值