迷宫问题:
假设有一个迷宫,里面有障碍物,迷宫用二维矩阵表示,标记为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;
}