【算法打卡day5 | 2026-02-10 周二 | 算法: BFS and BFS】7_卡码网103_高山流水

- 第 164 篇 -
Date: 2026 - 02- 10 (周二)
Author: 郑龙浩(仟墨)

2026-02-10 周二 | 算法打卡day5

文章目录

7_卡码网103_高山流水

**题目描述

现有一个 N × M 的矩阵,每个单元格包含一个数值,这个数值代表该位置的相对高度。矩阵的左边界和上边界被认为是第一组边界,而矩阵的右边界和下边界被视为第二组边界。

矩阵模拟了一个地形,当雨水落在上面时,水会根据地形的倾斜向低处流动,但只能从较高或等高的地点流向较低或等高并且相邻(上下左右方向)的地点。我们的目标是确定那些单元格,从这些单元格出发的水可以达到第一组边界和第二组边界。

输入描述

第一行包含两个整数 N 和 M,分别表示矩阵的行数和列数。

后续 N 行,每行包含 M 个整数,表示矩阵中的每个单元格的高度。

输出描述

输出共有多行,每行输出两个整数,用一个空格隔开,表示可达第一组边界和第二组边界的单元格的坐标,输出顺序任意。

输入示例

复制代码
5 5
1 3 1 2 4
1 2 1 3 2
2 4 7 2 1
4 5 6 1 1
1 4 1 2 1

输出示例

复制代码
0 4
1 3
2 2
3 0
3 1
3 2
4 0
4 1
cpp 复制代码
// Date: 2026-02-10 周一 Author:郑龙浩

// 7_卡码网103_高山流水_BFS_DFS

  

// 逆向思维思考:

// 也就是本身水是从中间向两边界流,现在是从两个边界往中间流,即从低往高流

// - 然后所有第一边界搜索的的坐标用first_visited数组去标记

// - 第二边界的用second_visited数组去标记

// 两者共同搜索过的坐标就是既可以到达第一也可以到到第二边界的坐标

  
  

// 方法1:DFS 方法2: BFS

#include "bits/stdc++.h"

using namespace std;

  

int direction[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

  

void dfs(vector <vector <int>>& grid, vector <vector <bool>>& visited, int x, int y) {

    if (visited[x][y] == true) { // 要先判断传入的坐标是否是被访问过的,以免出现问题

        return;

    }

    visited[x][y] = true; // 但凡传来的且没访问过的,都合格的,要标记访问过

    int height = grid.size();

    int width = grid[0].size();

    for (int i = 0; i < 4; i++) {

        int nextX = x + direction[i][0];

        int nextY = y + direction[i][1];

  

        // 只有 不越界 && 没访问过 && 下一个的坐标高度 > 当前坐标高度时,才会以下一个高度为中心搜索

        if (nextX >= 0 && nextX < height && nextY >=0 && nextY < width && visited[nextX][nextY] == false && grid[nextX][nextY] >= grid[x][y]) {

            dfs(grid, visited, nextX, nextY);

        }

    }

}

  

void bfs(vector <vector <int>>& grid, vector <vector <bool>>& visited, int x, int y) {

    if (visited[x][y] == true) {

        return;

    }

    queue <pair <int, int>> que; // 待搜索的加入到这里面来

    que.push({x, y});

  

    int height = grid.size();

    int width = grid[0].size();

    // 每次都以队列头为中心搜索四周,如果找到符合条件的,就将坐标加入到que待访问的队列

    while (!que.empty()) {

        pair <int, int> cur = que.front(); // 取出队列头

        que.pop(); // 只有取出队列的时候,才算访问过了

        visited[cur.first][cur.second] = true;

        for (int i = 0; i < 4; i++) {

            int nextX = cur.first + direction[i][0];

            int nextY = cur.second + direction[i][1];

  

            // 只有 不越界 && 没访问过 && 下一个的坐标高度 > 当前坐标高度时,才会加入que这个待搜索队列

            if (nextX >= 0 && nextX < height && nextY >=0 && nextY < width && visited[nextX][nextY] == false && grid[nextX][nextY] >= grid[cur.first][cur.second]) {

                que.push({nextX, nextY});

            }

        }

    }

}

  

int main(void) {

    ios::sync_with_stdio(0);

    cin.tie(0); cout.tie(0);

  

    int N, M; cin >> N >> M;

  

    vector <vector <int>> grid(N, vector <int> (M, 0));

    vector <vector <bool>> first_visited(N, vector <bool> (M, 0));

    vector <vector <bool>> second_visited(N, vector <bool> (M, 0));

  

    for (int i = 0; i < N; i++) {

        for (int j = 0; j < M; j++) {

            cin >> grid[i][j];

        }

    }

  

    // 处理左右两边(第一边界和第二边界)

    for (int i = 0; i < N; i++) {

        bfs(grid, first_visited, i, 0);

        bfs(grid, second_visited, i, M - 1);

    }

    // 处理上下两行(第一边界和第二边界)

    for (int i = 0; i < M; i++) {

        bfs(grid, first_visited, 0, i);

        bfs(grid, second_visited, N - 1, i);    

    }

  

    // 遍历每一个点,看是否能同时到达第一组边界和第二组边界

    for (int i = 0; i < N; i++) {

        for (int j = 0; j < M; j++) {

            if (first_visited[i][j] == true && second_visited[i][j] == true) {

                cout << i << ' ' << j << '\n';

            }

        }

    }

    return 0;

}
相关推荐
算法鑫探1 小时前
闰年判断:C语言实战解析
c语言·数据结构·算法·新人首发
WBluuue2 小时前
数据结构与算法:康托展开、约瑟夫环、完美洗牌
c++·算法
木子墨5162 小时前
LeetCode 热题 100 精讲 | 并查集篇:最长连续序列 · 岛屿数量 · 省份数量 · 冗余连接 · 等式方程的可满足性
数据结构·c++·算法·leetcode
王老师青少年编程3 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:均分纸牌
c++·算法·编程·贪心·csp·信奥赛·均分纸牌
EQUINOX13 小时前
2026年码蹄杯 本科院校赛道&青少年挑战赛道提高组初赛(省赛)第一场,个人题解
算法
萝卜小白3 小时前
算法实习Day04-MinerU2.5-pro
人工智能·算法·机器学习
Liangwei Lin3 小时前
洛谷 P3133 [USACO16JAN] Radio Contact G
数据结构·算法
weixin_513449963 小时前
PCA、SVD 、 ICP 、kd-tree算法的简单整理总结
c++·人工智能·学习·算法·机器人
code_pgf4 小时前
Qwen2.5-VL 算法解析
人工智能·深度学习·算法·transformer
Code-keys4 小时前
Android Codec2 Filter 算法模块开发指南
android·算法·音视频·视频编解码