1. 题目来源
2. 题目说明
3. 题目解析
方法一:bfs+硬编码+常规解法
本质就是一个深度遍历,理论上来讲 bfs
、dfs
都是可以的,按照数据范围进行判断的话,dfs
确实可能会爆栈,但还没到临界值啊。平时 bfs
写的很少,除过二叉树的层序遍历,所以一时间不知道怎么处理了…
每个街道都具备两个情况,总共有 6 个街道,那就对每个街道的连通情况进行硬编码即可。采用 bfs
进行遍历即可,相关注释也在代码中,就不进行解释了。
参见代码如下:
// 执行用时 :400 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :59 MB, 在所有 C++ 提交中击败了100.00%的用户
const int MAXN = 300 + 50;
bool vis[MAXN][MAXN];
queue<pair<int,int> > que;
// 判断下一块能否到达
bool check(int v, vector<int> arr){
for (auto x: arr) if (x == v) return true;
return false;
}
void todirect(int x, int y, int n, int m, vector<vector<int>>& grid, int k){
// 往左走,连通块为 1 4 6
if (k == 0)
if (y > 0 && check(grid[x][y - 1], {1, 4, 6}))
if (!vis[x][y - 1]) que.push(make_pair(x, y - 1)), vis[x][y - 1] = true;
// 往右走,连通块为 1 3 5
if (k == 1)
if (y + 1 < m && check(grid[x][y + 1], {1, 3, 5}))
if (!vis[x][y + 1]) que.push(make_pair(x, y + 1)), vis[x][y + 1] = true;
// 往上走,连通块为 2 3 4
if (k == 2)
if (x > 0 && check(grid[x - 1][y], {2, 3, 4}))
if (!vis[x - 1][y]) que.push(make_pair(x - 1, y)), vis[x - 1][y] = true;
// 往下走,连通块为 2 5 6
if (k == 3)
if (x + 1 < n && check(grid[x + 1][y], {2, 5, 6}))
if (!vis[x + 1][y]) que.push(make_pair(x + 1, y)), vis[x + 1][y] = true;
}
class Solution {
public:
bool hasValidPath(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size();
memset(vis, false, sizeof(vis));
// vis表示某个图块是否已经被访问
que.push(make_pair(0, 0)); vis[0][0] = true;
while(!que.empty()){
int x = que.front().first, y = que.front().second; que.pop();
// 当前图块的编号
int v = grid[x][y];
if (v == 1) {
todirect(x, y, n, m, grid, 0);
todirect(x, y, n, m, grid, 1);
}
if (v == 2) {
todirect(x, y, n, m, grid, 2);
todirect(x, y, n, m, grid, 3);
}
if (v == 3) {
todirect(x, y, n, m, grid, 0);
todirect(x, y, n, m, grid, 3);
}
if (v == 4) {
todirect(x, y, n, m, grid, 1);
todirect(x, y, n, m, grid, 3);
}
if (v == 5) {
todirect(x, y, n, m, grid, 0);
todirect(x, y, n, m, grid, 2);
}
if (v == 6) {
todirect(x, y, n, m, grid, 1);
todirect(x, y, n, m, grid, 2);
}
}
return vis[n - 1][m - 1];
}
};