P1746 离开中山路(BFS)

P1746 离开中山路

题目背景

《爱与愁的故事第三弹·shopping》最终章。

题目描述

爱与愁大神买完东西后,打算坐车离开中山路。现在爱与愁大神在 x1,y1 处,车站在 x2,y2 处。现在给出一个 n×n(n≤1000) 的地图,0 表示马路,1 表示店铺(不能从店铺穿过),爱与愁大神只能垂直或水平着在马路上行进。爱与愁大神为了节省时间,他要求最短到达目的地距离(每两个相邻坐标间距离为 1)。你能帮他解决吗?

输入格式

第 1 行包含一个数 n

第 2 行到第 n+1 行:整个地图描述(0 表示马路,1 表示店铺,注意两个数之间没有空格)。

n+2 行:四个数 x1,y1,x2,y2。

输出格式

只有 1 行,即最短到达目的地距离。

输入输出样例

输入

3
001
101
100
1 1 3 3

输出

4

说明/提示

对于 20% 数据,满足 1≤n≤100。

对于 100% 数据,满足 1≤n≤1000。

代码

#include <bits/stdc++.h>
#define N 1010  // 定义地图最大尺寸为 1010 (题目中 n ≤ 1000,留出额外空间)
using namespace std;

int dist[N][N];   // 存储从起点到各个位置的最短距离,初始化为 -1 表示未访问
char g[N][N];     // 地图数组,每个字符表示一个位置,'0' 表示马路(可通过),'1' 表示店铺(不可通过)
typedef pair<int,int> PII;  // 定义一个 pair 类型,用于存储坐标 (行, 列)
queue<PII> q;     // 定义队列用于 BFS 算法

int n;            // 地图的尺寸(地图为 n×n)
int dx[] = {1, -1, 0, 0}; // 四个方向移动的行偏移量:下、上、右、左
int dy[] = {0, 0, 1, -1}; // 四个方向移动的列偏移量

int x1, Y1, x2, y2;  // 起点坐标 (x1, Y1) 和目的地坐标 (x2, y2)

// BFS 函数:从起点搜索最短路径到目的地
int bfs(int x, int y) {
    // 初始化距离数组为 -1,表示所有位置均未访问
    memset(dist, -1, sizeof(dist));
    
    // 将起点 (x1, Y1) 入队,并将起点距离设为 0
    q.push({x1, Y1});
    dist[x1][Y1] = 0;
    
    // 当队列不为空时,进行 BFS 搜索
    while (!q.empty()) {
        // 取出队头元素,当前正在探索的位置
        auto t = q.front();
        q.pop();
        
        // 遍历四个可能的移动方向
        for (int i = 0; i < 4; i++) {
            int a = t.first + dx[i];  // 计算新位置的行号
            int b = t.second + dy[i]; // 计算新位置的列号
            
            // 判断新位置是否超出地图边界(注意坐标从 1 开始)
            if (a < 1 || b < 1 || a > n || b > n)
                continue;
            
            // 判断新位置是否为马路(只有 '0' 才可通行)
            if (g[a][b] != '0')
                continue;
            
            // 若该位置已经访问过,则跳过
            if (dist[a][b] >= 0)
                continue;
            
            // 将新位置加入队列等待后续探索
            q.push({a, b});
            // 更新新位置的距离:当前节点距离加 1
            dist[a][b] = dist[t.first][t.second] + 1;
            
            // 如果目的地 (x2, y2) 已经被访问,则直接返回最短距离
            if (dist[x2][y2] > 0)
                return dist[x2][y2];
        }
    }
    // 如果搜索结束仍未访问到目的地,返回 -1 表示不可达
    return -1;
}

int main() {
    // 读入地图尺寸 n
    scanf("%d", &n);
    
    // 读入地图,每行输入一个字符串,注意字符串下标从 1 开始存储到数组 g 中
    for (int i = 1; i <= n; i++) {
        scanf("%s", g[i] + 1);
    }
    
    // 读入起点和目的地的坐标:x1, Y1 为起点;x2, y2 为目的地
    scanf("%d %d %d %d", &x1, &Y1, &x2, &y2);
    
    // 调用 BFS 函数计算最短路径距离
    int res = bfs(x1, Y1);
    
    // 输出最短路径距离,若不可达则输出 -1
    printf("%d\n", res);
    
    return 0;
}

题目《P1746 离开中山路》描述了如下情境:

  • 给出一个

    n×nn \times nn×n

    的地图,地图上每个位置用字符表示,

    • '0' 表示马路(可以通行),
    • '1' 表示店铺(不能穿过)。
  • 起点位于 (x1,y1)(x_1, y_1)(x1,y1),车站(目的地)位于 (x2,y2)(x_2, y_2)(x2,y2)。

  • 只能沿水平方向或垂直方向行走(每步距离为 1),要求求出从起点到目的地的最短距离,若无法到达则输出 -1。

2. 建模与数据结构
  • 地图表示
    使用二维字符数组 g[][] 存储地图,数组下标从 1 开始便于与题目描述对应。
  • 距离记录
    使用二维整型数组 dist[][] 存储从起点到每个位置的最短步数,初始化为 -1 表示该位置还未被访问过。
  • 队列
    为实现广度优先搜索(BFS),使用 STL 中的 queue 存储待探索的位置。
3. 算法选择:广度优先搜索 (BFS)
  • 原因
    BFS 能够在无权图中(每步代价均为 1)快速找到从起点到任意位置的最短路径。

  • 步骤

    1. 初始化

      • 将起点 (x1,Y1)(x_1, Y_1)(x1,Y1) 的距离设为 0,并将其放入队列。
    2. 搜索过程

      • 每次从队列中取出一个节点,依次检查其上下左右四个相邻位置。
      • 对每个相邻位置,进行以下判断:
        • 是否在地图范围内;
        • 是否为马路(只有 '0' 可通行);
        • 是否已经访问过。
      • 若满足条件,则更新该位置的距离(当前节点的距离加 1),并将其加入队列。
      • 若目的地 (x2,y2)(x_2, y_2)(x2,y2) 被访问,则可以提前返回最短距离。
    3. 结束条件

      • 如果队列为空仍未能到达目的地,则说明目的地不可达,返回 -1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

week_泽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值