第五十四章 DFS进阶(二)——迭代加深

文章介绍了DFS的缺陷,即可能在错误路径上浪费大量时间。为解决此问题,文章详细讲解了迭代加深的概念,限制搜索深度并逐步增加,避免深度过深。复杂度分析表明,即使在最坏情况下,影响也相对有限。通过一个具体例题展示了如何应用迭代加深算法,该题要求生成特定序列,迭代加深能有效应对不同情况。
摘要由CSDN通过智能技术生成

一、DFS的缺陷

我们知道DFS是一条路走到黑,直到将整条路走完以后才会回头。

这就导致了一个问题,路很多,你没有办法确定当下走的路就是正确的,同时,如果这条路是错误的,却又无比的长。这就会导致你在错误的路上越走越远。

示意图如下图所示:
在这里插入图片描述
红色点是答案,而如果我们不幸地从左侧的最长的方案开始搜索的话,就会导致我们在错误的路上越走越远。那么为了解决这类极端的情况,我们就需要使用迭代加深的算法。

二、迭代加深

1、什么是迭代加深

迭代加深就是我们规定一个DFS的深度,如果到了该深度还没有找到答案的话,我们就及时收手,换一条路搜索,如果在该深度下,没有任何一条路是答案的话,我们就增加DFS的深度,再从头开始来一遍。

很明显这样做的话,我们就解决了在一条错误地路上越走越远的困境,但是很明显,在每个深度中,它都在不断地从头尝试每一种方案,这就造成了很多重复的步骤,那么这种重复的现象对我们时间复杂度有什么影响呢?

我们看下面的分析。

2、复杂度分析

我们这里分析的主要是刚才的问题,重复的搜索是否会影响到该算法的效率。我们看一下最坏情况下,假设我们每次只有两个选择,即整个搜索树是一个满二叉树,此时我们这个算法的时间复杂度是怎样的。

在这里插入图片描述
假设我们遍历了每一个分支,那么在遍历最后一排的时候,我们会重复遍历最后一排上面的所有节点,但是即使是在这种情况下,我们重复遍历一遍的节点数也只是接近于我们最后一排的节点数。

也就是说在最坏条件下,影响也没有那么大。

3、算法步骤

这个算法的过程还是比较简单的,就是我们把搜索深度设置为1,然后开始搜索,如果当前深度没有搜到答案的话,我们就递增深度。直到搜索到答案,这个过程可以写成一个while循环。

三、例题

1、问题

在这里插入图片描述

2、分析

这道题的话,需要满足几个条件:
1、第一个元素和最后一个元素是固定的。
2、中间的元素是严格单调递增的。
3、当前元素等于前面某两个的和

那么最坏条件下, 就是从1,2,3,4,5…开始逐渐递增,那么到达最大值的话,大概是100层。

最好条件下,就是指数级别的增长,1,2,4,8,16,32,64,128。最多8层。

我们发现最好情况和最坏情况之间差了90多层。面对这种极端情况,我们就需要使用我们的迭代加深了。

3、代码

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 110;
int path[N];
int n;

bool dfs(int u, int deep)
{
	if(u > deep)return false;
	if(path[u - 1] == n)return true;

	bool st[N] = {0};
	for(int i = u - 1; i >= 0; i -- )
		for(int j = i; j >= 0; j -- )
		{
			int x = path[i] + path[j];
			if(x > n || x <= path[u - 1] || st[x])continue;
			st[x] = true;
			path[u] = x;
			if(dfs(u + 1, deep))return true;
		}

	return false;
}

void solve()
{
	while(cin >> n, n)
	{
		path[0] = 1;
		
		int deep = 1;
		
		while(!dfs(1, deep))deep ++;
    
		for(int i = 0; i < deep; i ++ )
			cout << path[i] << " ";
		
		cout << endl;
	}

	
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值