电脑鼠走迷宫(DFS+BFS)

在这里插入图片描述

简介:

IEEE国际标准电脑鼠走迷宫竞赛,简单来说是使用微控制器、传感器和机电运动部件构成的一种智能行走机器人,本文仅对”到达迷宫终点",这一问题进行算法上的思索与解决。

在这里插入图片描述

方法:

1-DFS(深度优先搜索):

  • 算法简介:dfs,又叫深搜,暴搜,通过朴实的暴力来解决问题。同一道题目,搜索的方式有很多,最重要的是找到一种顺序去进行搜索。一般通过二叉树进行递归形式的回溯搜索,例如我们有寻找1-3的全排列,如下图(图片来自Hasity,感谢大佬)

img

一共三个坑,一个坑填一个数,我们通过开设一个状态数组来标记当前尚未使用的数,每次填入坑中,当一个节点无路可走或走到头是,回溯到最近的一个节点去搜索下一条路

核心操作:

void dfs(int u)
{
	if(u == n)//坑满了
	{
		for(int i = 0; i < n; i ++) 
		cout << path[i] << " ";
		cout << endl;  
		return;
	}
	for(int i = 1; i <= n; i ++)
	if(!st[i])//找没用过的填坑
	{
		path[u] = i;//填坑
		st[i] = true;
		dfs(u + 1);//分支向下走
		st[i] = false;//恢复现场
	}
}
  • 小迷宫,走起来

思路:小鼠从起点出发,一旦撞墙就返回到上一岔路口,尝试不同的转向,尝试过的道路标记一下,不走回头路浪费时间,不断深入迷宫,最终到达终点。

题境:给出一个n*m的01迷宫,0可走,1不可走,从(1, 1)走到(n, m)

核心操作:

void dfs(int x, int y, int cnt)
{
	if(x == n && y == m)
	{
		tt ++;//记录从起点到终点的方案数
		if(cnt < ans)//记录最短步数
		ans = cnt;

		return;
	}
	int f[5] = {1, 0, -1, 0, 1};//方向数组,四方通行
	for(int i = 0; i < 4; i ++)
	{
		int xx = x + f[i], yy = y + f[i + 1];
		if(xx > 0 && yy > 0 && xx <= n && yy <= m && !g[xx][yy] && !st[xx][yy])
		{
			st[xx][yy] = 1;
			dfs(xx, yy, cnt + 1);
			st[xx][yy] = 0;//及时回溯,下一条路
		}
	}
}
  • 分析:深度搜索在走迷宫时只有走到死路才会返回,遍历所有可能的路线直到终点才能找到最短路径,适合枚举所有路线方案,但对于速度为王的迷宫来说,并非上策。当然也可以通过添加一些条件,少走一些弯路,达到’剪枝优化’的目的。

2-BFS(广度优先搜索):

  • 算法简介:bfs,又叫宽搜,通过广度优先遍历,一层层的向外拓展,搜索所有距离为i++的点,那么第一次搜到的目标距离即为最短距离。
  • 如图,题意与dfs的小迷宫一样,从(1,1)走到(5,5),我们每次都只看比当前位置+1的点,一层层的向外拓展,直到终点出现,即为最短距离。(下图来自Acwing-y总,最生动形象,感谢y总)

在这里插入图片描述

  • 小迷宫,走起来(2.0)

思路:小鼠从起点出发,沿着交叉路口的某一分支前进,到下一个路口的时候回去检查,反复循环,达到一层层向外拓展的目的,直到找到终点。(听起来好像更麻烦了,但在实操里时间复杂度还是比暴搜低的)

代码思路:用一个队列来实现(STL大法,数组模拟自己够呛),开一个距离数组,来表示每个点到起点的距离,初始为-1,存入起点,开始上下左右向外拓展,每到一个新位置,距离+1,并存入新位置,注意,当开始探索下一位置时,岔路口的先前存入的坐标要弹出队列,表示不再回头记录。最终当队列为空时,即无路可走,到达终点,此时终点的距离数组的坐标即为所求最短距离。(描述粗糙,见谅)

核心操作:

int bfs()
{
	queue<PII> q;
	q.push({0, 0});
	
	memset(d, -1, sizeof d);//距离数组初始化
	d[0][0] = 0;
	
	while(!q.empty())
	{
		auto t = q.front();
		q.pop();//勿忘弹出,再也不见
		for(int i = 0; i < 4; i ++)//方向数组同上
		{
			int x = t.first + f[i], y = t.second + f[i + 1];
			if(x < n && y < m && x >= 0 && y >= 0 && g[x][y] == 0 && d[x][y] == -1)
			{
				d[x][y] = d[t.first][t.second] + 1;//比上一步距离起点+1
				q.push({x, y});//这点要压入队列
			}
		}
	}
	return d[n - 1][m - 1];//最终答案,终点距离起点的最短距离
}
  • 分析:广度优先搜索从结果上来看,层层拓展的找寻方式的相对暴搜少走许多弯路,但还是需要小鼠不断去尝试进行移动。

走向实际:

洪水填充算法:一张图上有多个区域,不同的区域用不同颜色区分,同一个区域的所有点的颜色 (oldColor) 都是相同的。给定图上的一个点,称为种子点,然后从种子点出发,把种子点所属的封闭区域用新颜色 (fillColor) 填充,这就是 “洪水填充”。(了解不深)

c361d66e9d50a17cd3fed25594ecdd10.png

实现:用DFS和BFS均可进行实现,上图为通用的四邻域填充法,当然也有八向填充,接受三个参数—起始节点,目标节点以及提取对象要执行的处理。

实际:假设小鼠与终点之间无障碍,小鼠可以直接到达终点,此时在这条"最短路径"上,遇到墙壁便标记起来,并重新规划路线,一直朝终点前进。"祖传代码"会标记出每一点距离终点的距离,碰到墙壁处返回,数字重新标记,此时小鼠沿着递减路线直达终点便是最短路线。任何事不会有完美的,洪水填充算法,不保证第一次便找到最佳路径,但其进一步优化了策略,避免了行走许多重复路线。

杂谈:

算法总归要应用于实际,电脑鼠走迷宫的比赛需要电子信息,程序设计,机械工程,自动控制,传感与测试等多项技术知识。向小鼠走迷宫,我们往往会将目光局限在"最短",可最短不一定最快,转弯速度同样影响平均速度,比起现实,我们需要考虑的还远远不止编译器上的几行代码。

在近期的全国大学生机器人大赛高校对抗赛(机甲大师赛)中,电子科技大学的兔子机器人一跃而起,抢占先机,赢下半决赛冠军,并在之后与广州城市理工学院的决赛中,跳跃式拿下最后总冠军。这是一场创新性的比赛,不拘泥于传统,推陈出新,科技的进步同样如此。

推荐到B站去观看,从预选赛到最后的决赛均有,观感不错。
在这里插入图片描述

本文参考:(https://zhuanlan.zhihu.com/p/51538950),b站洪水填充,acwing

  • 14
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值