题解 [SP7579] YOKOF - Power Calculus

该博客介绍了如何使用迭代加深深度优先搜索(IDDFS)解决一个数学问题,即给出正整数n,找出使1经过加法或减法运算变为n的最小步数。IDDFS结合了DFS的深度探索和BFS的空间效率,通过不断增大深度限制来避免深陷无效分支。博客中详细解释了IDDFS的四部分过程,并提供了一个C++实现的代码示例。
摘要由CSDN通过智能技术生成

题解 [SP7579] YOKOF - Power Calculus

Luogu Link

题目显然可以转化为:

给出正整数 n n n,若只能使用加法或减法,输出使 1 1 1 经过运算(自己加或减自己,以及加或减运算过程中产生的中间结果)变成 n n n 的最少步数。

使用 IDDFS 求解。

IDDFS,即迭代加深的 DFS,就是在 DFS 过程中添加一个“最大深度值”,每次 DFS 时如果递归深度大于这个值就强制结束递归。如果没搜到目标,就令最大深度值 + 1 +1 +1,继续搜一遍。这样虽然会重复搜搜索树上浅层节点,但是浅层节点数相对于深层节点数可以忽略不计(搜索树上,大部分情况 1 ∼ n 1\sim n 1n 层的节点数远小于 n + 1 n+1 n+1 层节点)。

那 IDDFS 有什么好处呢?它既可以防止 DFS 陷入错误的搜索分支耗费时间,又不像 BFS 一样占用大空间。如果搜索树分支很多,且目标在浅层节点上,可以考虑 IDDFS。

IDDFS 的过程可以大致分为四部分:

  1. 枚举“最大深度值”,从 1 1 1 开始,每次进行 DFS,成功搜到就退出,失败就 + 1 +1 +1 继续搜。
  2. DFS 中,如果递归层数大于最大深度值,判断答案是否正确。
  3. 进行可行性剪枝(如果当前的答案怎么都达不到目标,直接剪枝)。
  4. 枚举分支,继续递归。

本题的可行性剪枝为:记录当前搜到的所有数的最大值,设为 m x mx mx,当前层数设为 i i i,最大深度为 m d md md,则如果递归到 m d md md 层,那么最大只可能搜到 m x × 2 m d − i mx\times 2^{md-i} mx×2mdi,这个值如果小于目标直接剪枝。

//SP7579
#include <bits/stdc++.h>
using namespace std;

int n, a[20], md;

bool dfs(int dep, int mx){
	if(a[dep] == n) return true;
	if(dep >= md) return false;
	if(mx*(1<<(md-dep))<n) return false;
	for(int i = 0; i <= dep; ++ i){
		a[dep+1] = a[dep] + a[i];
		if(dfs(dep+1, max(mx, a[dep+1]))) return true;
		a[dep+1] = abs(a[dep]-a[i]);
		if(dfs(dep+1, max(mx, a[dep+1]))) return true;
	}
	return false;
}

int main(){
	while(true){
		scanf("%d", &n);
		if(n == 0) return 0;
		if(n == 1){ puts("0"); continue; }
		a[0] = 1;
		for(md = 1; ; ++ md)
			if(dfs(0, 1)){ printf("%d\n", md); break; }
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值