BFS(一)广度优先搜索(Breadth First Search) ------ 一石激起千层浪

迷宫问题:
假设有一个迷宫,里面有障碍物,迷宫用二维矩阵表示,标记为0的地方表示可以通过,标记为1的地方表示障碍物,不能通过。现在给一个迷宫出口,让你判断是否可以从入口进来之后,走出迷宫,每次可以向任意方向走。

在一个 106 x 106 的网格中,每个网格上方格的坐标为 (x, y) 。

现在从源方格 source = [sx, sy] 开始出发,意图赶往目标方格 target = [tx, ty] 。数组 blocked 是封锁的方格列表,其中每个 blocked[i] = [xi, yi] 表示坐标为 (xi, yi) 的方格是禁止通行的。

每次移动,都可以走到网格中在四个方向上相邻的方格,只要该方格 不 在给出的封锁列表 blocked 上。同时,不允许走出网格。

只有在可以通过一系列的移动从源方格 source 到达目标方格 target 时才返回 true。否则,返回 false。

可以使用DFS解决,直接上代码吧:和之前dfs岛屿问题基本相同。(当然,大迷宫肯定会超时)

int NextP[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
class Solution {
public:
    bool dfs(vector<vector<int>>& grid, int curX, int curY, 
             int endX, int endY, vector<vector<bool>>& book)
    {
        if(curX==endX && curY == endY)
        {
            return true;
        }
        for(int i = 0; i < 4; ++i)
        {
            int newX = curX + NextP[i][0];
            int newY = curY + NextP[i][1];
            if(newX>=1000000 || newX<0 ||
               newY>=1000000 || newY<0)
               continue;
            if(book[newX][newY]==false && grid[newX][newY]==0)
                dfs(grid, newX, newY, endX, endY, book);
        }
        return false;
    }
    bool isEscapePossible(vector<vector<int>>& blocked, vector<int>& source, vector<int>& target) {
        int beginX = source[0];
        int beginY = source[1];
        int endX = target[0];
        int endY = target[1];
        int row = blocked.size();
        int col = blocked[0].size();
        vector<vector<int>> grid(1000000, vector<int> (1000000, 0));
        for(auto e : blocked)
        {
            grid[e[0]][e[1]] = 1;
        }
        vector<vector<bool>> book(1000000, vector<bool> (1000000, false));
        return dfs(grid, beginX, beginY, endX, endY, book);
    }
};

 上面的代码就会超时!!!并且如果有多条路径的话,dfs找出来的路径一般不是最短路径,这里就需要使用到BFS算法了,更重要的是体会思想了。

BFS解决迷宫问题

假设是一个10*10的迷宫,入口在(1,1)的位置,出口在(8,10)的位置,通过(1,1)一步可以走到的位置有两个(1,2),(2,1)但是这两个点并不是出口,需要继续通过这两个位置进一步搜索,假设现在在(1,2),下一次一步可以到达的新的位置为(1,3),(2,2)。而通过(2,1)可以一步到达的新的位置为(2,2),(3,1),但是这里(2,2)是重复的,所以每一个点在走的过程中需要标记是否已经走过了。两步之后,还没没有走到出口,这时候需要通过新加入的点再去探索下一步能走到哪些新的点上,重复这个过程,直到走到出口为止。

代码解析这个过程,最关键的步骤用当前位置带出新的位置,新的位置可以存放在一个vector或者队列中。位置需要用坐标表示,这里封装出一个node。
 

using namespace std;
#include<iostream>
#include<string>
#include<set>
#include<queue>
int nextP[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };

class Node
{
public:
	int x;
	int y;
	Node(int a, int b)
	{
		x = a;
		y = b;
	}
};
class Solution
{
public:
	bool bfs(vector<vector<int>>& grid, int curX, int curY, int endX, int endY)
	{
		int row = grid.size();
		int col = grid[0].size();
		queue<Node> q;	// 创建一个队列存放当前位置
		q.push(Node(curX, curY));
		vector<vector<bool>> book(row, vector<bool>(col, false)); // 一个标记数组,表示元素是否访问过
		book[curX][curY] = true;	// 刚开始访问位置设置为true
		while (!q.empty())
		{
			Node cur = q.front();	// cur指向队头  并pop
			q.pop();
			if (cur.x == endX && cur.y == endY)	// 如果到了目标位置返回true
			{
				return true;
			}
			for (int i = 0; i < 4; ++i)	// 根据cur上下左右移动
			{
				int newX = cur.x + nextP[i][0];
				int newY = cur.y + nextP[i][1];
				if (newX >= row || newX < 0 ||
					newY >= col || newY < 0)
					continue;
				if (book[newX][newY] == false && grid[newX][newY] == 0)
				{
					q.push(Node(newX, newY));	// 新的位置可以走就放入队列
					book[newX][newY] = true;
				}
			}
		}
		return false;
	}
};

void Test()
{
	int row, col;
	cin >> row >> col;
	vector<vector<int>> grid(row, vector<int>(col)); // 初始化数据
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			cin >> grid[i][j];
		}
	}
	Solution s;
	bool flag = s.bfs(grid, 0, 0, row - 1, col - 1);
	if (flag)
		cout << "true" << endl;
	else
		cout << "false" << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值