#搜索算法# 从迷宫问题初步了解DFS&&BFS

*来源 * 啊哈算法!
有一天,小哈一个人去玩迷宫。但是方向感不好的小哈很快就迷路了。小哼得知后便去解救无助的小哈。此时的小哼已经弄清楚了迷宫的地图,现在小哼要以最快的速度去解救小哈。那么,问题来了…
在这里插入图片描述输入

5 4
0 0 1 0
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 1 4 3

输出

7

我们先来分析一下可能的道路
在这里插入图片描述
如图
此图表现的思想就是DFS(深度优先搜索)
也就是按既定的顺序进行搜寻
如(右下左上)
从起点往右走 直到走不通就尝试往下走
如果上下左右都走不通
就回溯到上一个状态(继续尝试当前状态的其他方向)
然后上代码 体会一下

#include<stdio.h>
int n, m, p, q, min = 99999999;
int a[51][51], book[51][51];//book用来标志是否走过
void dfs(int x, int y, int step)
{
	int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };//四个方向,注意行列
	int tx, ty, k;
	if (x == p && y == q)
	{
		if (step < min)//更新最少步数
			min = step;
		return;
	}
	for (k = 0; k <= 3; k++)
	{
		tx = x + next[k][0];//更新位置
		ty = y + next[k][1];
		if (tx<1 || tx>n || ty<1 || ty>m)//判断下一步是否在界面内
			continue;
		if (a[tx][ty] == 0 && book[tx][ty] == 0)//没有障碍且没有走过就走
		{
			book[tx][ty] = 1;
			dfs(tx, ty, step + 1);//递归实现遍历所有情况
			book[tx][ty] = 0;
		}
	}
	return;//这个return 很重要 不然就死循环了
}
int main()
{
	int i, j, startx, starty;//当前位置 出口位置
	scanf("%d %d", &n, &m);
	for (i = 1; i <= n; i++)
		for (j = 1; j <= m; j++)
			scanf("%d", &a[i][j]);
	scanf("%d %d %d %d", &startx, &starty, &p, &q);
	book[startx][starty] = 1;
	dfs(startx, starty, 0);
	printf("%d", min);
	getchar();//暂停一下 怕闪退
	return 0;
}

再谈BFS(广度优先搜索)
也就字面意思
广度(脑补一下丢块石子在池中,波纹一圈一圈荡开)
BFS也就是类似的意思
一层一层的去搜索并标记;
因此BFS找到的第一个可行解必是最优解 程序就可退出
emmmm我没找到图 自己脑补吧
要用队列来实现
就是说从当前点开始
向外扩展一圈(当然不能是障碍物)
并且把外面一圈标记+1;
再将外面一圈依次标记更外面一圈 再标记加一
知道终点被标记 那么标记的值就是最短步数!!

#include <iostream>
#include <cstdio>>
#include <algorithm>
#include <queue>
#define INF 99999999
using namespace std;
typedef struct Node {
    int x, y;//当前坐标
    int step;//步数
}node;
const int maxn = 105;
int minx = INF;
int n, m;
int sx, sy, hx, hy;
int a[105][105];
int vis[maxn][maxn];
int dir[4][2] = { 0,1,-1,0,0,-1,1,0 };//四个方向
void bfs(int x, int y) {
    node p, q;
    p.x = x;
    p.y = y;
    p.step = 0;
    queue<node> pq;
    pq.push(p);
    while (!pq.empty()) {
        p = pq.front();
        pq.pop();
        if (p.x == hx && p.y == hy) {
            minx = p.step;
            return;
        }
    }
    for (int i = 0; i < 4; i++) {
        q.x = p.x + dir[i][0];
        q.y = p.y + dir[i][1];
        q.step = p.step + 1;
        if (q.x<1 || q.x>n || q.y<1 || q.y>m)//判断是否越界
            continue;
        if (!vis[q.x][q.y] && a[q.x][q.y] != 1) {//如果这个点没有走过或者这个点不是障碍物,则可以走
            vis[q.x][q.y] = 1;
            pq.push(q);
        }
    }
    return;
}
int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &a[i][j]);
        }
    }
    scanf("%d %d %d %d", &sx, &sy, &hx, &hy);
    vis[sx][sy] = 1;
    bfs(sx, sy);
    if (minx == INF) printf("No Way!\n");
    else printf("%d\n", minx);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值