深度优先搜索(DFS)遍历图找到出口

16 篇文章 0 订阅

最近重新复习了一遍DFS,做下笔记

代码运行效果图:

代码:

#include <iostream>
using namespace std;
#include <list>
#include <stack>
#include <Windows.h>
int map[10][10]=
{
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
	1, 2, 1, 0, 1, 0, 0, 0, 0, 1,
	1, 0, 1, 0, 1, 0, 0, 0, 0, 1,
	1, 0, 1, 0, 1, 1, 1, 1, 0, 1,
	1, 0, 1, 0, 1, 1, 1, 1, 0, 1,
	1, 0, 1, 1, 0, 0, 0, 1, 0, 1,
	1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
	1, 0, 1, 0, 0, 0, 0, 0, 0, 1,
	1, 0, 0, 0, 0, 0, 1, 0, 3, 1,
	1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
void render()
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			switch (map[i][j])
			{
			case 0:
			case 9:
				cout << "  ";
				break;
			case 1:
				cout << "墙";
				break;
			case 2:
				cout << "入";
				break;
			case 3:
				cout << "出";
				break;
			default:
				break;
			}
		}
		cout << endl;
	}
}
struct VEC2
{
	int x;
	int y;
};
// 寻找入口
VEC2 findEnter()
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			VEC2 p;
			if (2 == map[i][j])
			{
				VEC2 p = {i,j};
				return p;
			}
		}
	}
	VEC2 p;
	return p;
}
// 创建路径链表,保存走过的路径 
list<VEC2> _listPath;
// 创建分岔路口栈,用于保存分岔路口 
stack<VEC2> _stackCorss;
// 寻找路径
void find(VEC2 pos)
{   
    //p保存下一个要走的节点 
	VEC2 next;
	//记录周围四个点的空地的个数 
	int num = 0; 
	//每次从右开始,逆时针查找周围的四个位置,这个顺序决定了这个算法的走向,可以自由改变
	for (int i = 1; i >= -1; i--)
	{
		for (int j = -1; j <=1; j++)
		{
			//不考虑斜着走的情况 
			if (abs(i)  == abs(j))
				continue;
			//如果是空地 
			if (0 == map[i + pos.x][j + pos.y]) 
			{
				next.x = i + pos.x;
				next.y = j + pos.y;
				num++;
			}
			//如果是终点 
			else if (3 == map[i + pos.x][j + pos.y])
			{
				_listPath.push_back(pos);
				return;
			}
		}
	}
	//当前位置周围只有一个空地,直接往下走 
	if (num == 1)
	{
	    //标记此位置已经访问过
		map[pos.x][pos.y] = 9;
		_listPath.push_back(pos);
		find(next);
	}
	//当前位置周围没有空地,回溯,取出栈顶元素,从这个元素的位置开始搜索 
	else if(num == 0)
	{
		//标记此位置已经访问过
		map[pos.x][pos.y] = 9;
		// 获取栈顶元素
		pos = _stackCorss.top();
		// 出栈
		_stackCorss.pop();
		// 删除链表中无效路径
		for (list<VEC2>::iterator it = _listPath.begin();
			it != _listPath.end();
			it++)
		{
			VEC2 iPos = *it;
			if (iPos.x == pos.x && iPos.y == pos.y)
			{
				_listPath.erase(it, _listPath.end());
				break;
			}
		}
		//从当前出栈的节点开始继续搜索可行路径 
		find(pos);
	}
	//当前位置周围有多个空地,即为分岔路口,入栈 
//(注意只要周围空地>1,就每次把这个位置入栈,因为回溯时会出栈,所以只要周围还有空地,回溯时就又从这个位置开始搜索)
	else
	{
		//将当前位置存放到路径链表中 
		_listPath.push_back(pos);
		//将当前位置入栈
		_stackCorss.push(pos);
		//标记此位置已经访问过
		map[pos.x][pos.y] = 9;
		//从下一个位置开始搜索可行路径 
		find(next);
	}
}
// 行走动画
void go()
{
	VEC2 p = _listPath.front();
	map[p.x][p.y] = 2;
	system("CLS");
	render();
}
int main()
{
	render();
	// 寻找起点
	VEC2 startpos = findEnter();
	// 寻找路径
	find(startpos);
	//_listPath.push_back(startpos);
	while (_listPath.size() > 0)
	{
		go();
		// 删除头
		_listPath.pop_front();
		// 
		Sleep(500);
	}
	return 0;
}

放上一张自己画的路径图,自己跟着程序走一遍就能理解的,DFS最主要用到了栈和递归,

当你走到一个位置有三种情况,

1、四周一直只有一个空地,那么只能往这个空地走;

2、这个位置的四周不止一个可以走的点,你就需要用栈来保存这样的分岔位置,这样如果你选择了其中一个位置往下走而走不下去的时候,就会回溯(也就是这个递归的回溯),从栈中取出栈顶元素,即分岔位置,然后从分岔位置开始尝试走其他没有走过的位置;

3、四周没有空地,从栈中取出栈顶元素,即上一个可以分岔的位置,然后从分岔位置开始尝试走其他没有走过的位置。注意栈可能为空,那就说明你一开始走就是四周都走不了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值