📅  最后修改于: 2023-12-03 15:41:09.747000             🧑  作者: Mango
本题涉及到连通性问题,需要使用图论中的BFS算法。
在一个$N \times M$的方格图上,有一些空地以及一些障碍物。现在给出其中一个起点和一个终点,求从起点到终点最少需要经过多少个空地。
第一行包含三个整数$N, M, K$,分别表示方格图的行数、列数以及障碍物的数量。
接下来$K$行,每行给出2个整数,表示一个障碍物的行和列。
最后一行给出4个整数$R_1, C_1, R_2, C_2$,表示起点和终点的坐标。
输出一个整数,表示从起点到终点最少需要经过多少个空地,如果无法到达,则输出$-1$。
$1 \le N, M \le 1000$
$0 \le K \le 10^4$
$1 \le R_1, R_2 \le N$
$1 \le C_1, C_2 \le M$
首先根据输入的障碍物坐标,将障碍物信息存储到一个bool类型的二维数组中,表示该位置是否为障碍物。
接着从起点开始进行BFS搜索,标记visit数组表示该点是否已经被访问过。将搜索到的空地的步数用dis数组记录下来。
当在搜索中找到终点时,直接返回该点对应的步数即可。当搜索结束后还没有找到终点,说明无法到达,返回$-1$。
BFS算法的时间复杂度为$O(V+E)$,其中$V$为节点数,$E$为边数。对于本题,最坏情况下,所有空地都是连通的,边数为$\Theta(NM)$,时间复杂度为$\Theta(NM)$。
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1010;
int n, m, k;
bool g[N][N], visit[N][N];
int dis[N][N];
int sx, sy, fx, fy;
// 方向数组,用于确认新的坐标是否符合要求以及决定下一个搜索方向
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
void bfs()
{
queue<pair<int, int>> q;
q.push({sx, sy});
dis[sx][sy] = 0;
visit[sx][sy] = true;
while (q.size())
{
auto t = q.front();
q.pop();
int x = t.first, y = t.second;
if (x == fx && y == fy)
return;
// 尝试向四个方向拓展
for (int i = 0; i < 4; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
// 判断新坐标是否符合要求
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !g[nx][ny] && !visit[nx][ny])
{
dis[nx][ny] = dis[x][y] + 1;
visit[nx][ny] = true;
q.push({nx, ny});
}
}
}
}
int main()
{
cin >> n >> m >> k;
while (k--)
{
int x, y;
cin >> x >> y;
g[x][y] = true;
}
cin >> sx >> sy >> fx >> fy;
bfs();
if (dis[fx][fy] == 0x3f3f3f3f)
cout << -1 << endl;
else
cout << dis[fx][fy] << endl;
return 0;
}