📜  算法测验| SP2竞赛1 |问题16(1)

📅  最后修改于: 2023-12-03 15:41:09.747000             🧑  作者: Mango

算法测验 | SP2竞赛1 | 问题16

本题涉及到连通性问题,需要使用图论中的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)$。

C++代码
#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;
}
参考资料
  1. BFS详解及应用
  2. SP2竞赛1官网