一、题目链接
二、题目分析
(一)算法标签
bfs
(二)解题思路
首先,本题考查宽搜(bfs); 其次, 熟悉bfs框架可以帮我们快速解题,bfs框架如下:
宽搜(bfs)框架
一、 判重数组st[] 一般入队时判重(保证每个点只会入队一次,从而保证时间复杂度是线性的) (特殊情况出队时判重,如A*算法、Dijkstra算法)
二、 queue
1. queue ← \leftarrow ← 初始状态
2. while (queue非空)
{
t ← \leftarrow ← 队头元素
队头元素出队列
for (扩展t)
{
ver ← \leftarrow ← 新节点
if (!st[ver])
{
ver → \rightarrow → 队尾
}
}
}
宽搜(bfs)本质
是从一个状态扩展到另一个状态
。不同宽搜题目的不同点
在于状态的定义
上
主要有两大类
, 第一类
是走迷宫类
问题,矩阵的每一个格子
是一个状态;第二类是八数码、数独类
问题,整个矩阵(一个数组)
是一个状态,每次枚举它能变成什么状态
三、AC代码
解法一:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
#define x first
#define y second
const int N = 210;
char g[N][N];
int dist[N][N];
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int T, n, m;
int bfs(PII start)
{
// 初始化dist数组(同时充当st数组)
memset(dist, -1, sizeof dist);
dist[start.x][start.y] = 0;
// 初始化queue
queue<PII> q;
q.push(start);
while (!q.empty()) // 队列非空
{
auto t = q.front(); // 取队首元素
q.pop(); // 队首元素出队列
for (int i = 0; i < 4; i ++ ) // 扩展首元素
{
int x = t.x + dx[i], y = t.y + dy[i];
if (x < 0 || x >= n || y < 0 || y >= m) continue; // 越界
if (g[x][y] == '#') continue; // 障碍物
if (dist[x][y] != -1) continue; // 未被遍历
dist[x][y] = dist[t.x][t.y] + 1;
if (g[x][y] == 'E') return dist[x][y];
q.push({x, y});
}
}
return -1;
}
int main()
{
cin >> T;
while (T -- )
{
cin >> n >> m;
for (int i = 0; i < n; i ++ ) scanf("%s", g[i]);
PII start;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (g[i][j] == 'S') start = make_pair(i, j);
int distance = bfs(start);
if (distance == -1) puts("oop!");
else cout << distance << endl;
}
return 0;
}