当前位置: 首页 > news >正文

06高山流水 图论

\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
提示信息

img

图中的蓝色方块上的雨水既能流向第一组边界,也能流向第二组边界。所以最终答案为所有蓝色方块的坐标。

数据范围:

1 <= M, N <= 100。


//这个方法比较好,时间复杂度较低,且也没有增加难度
#include<iostream> 
#include<vector>
using namespace std;
int dir[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]) return;  visited[x][y] = true;for(int i=0;i<4;i++){int nextx = x + dir[i][0];int nexty = y + dir[i][1];if(nextx < 0|| nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()){continue;}//只有反向可以流过去的才进入dfs去继续标记if(grid[x][y] <= grid[nextx][nexty]){dfs(grid,visited,nextx,nexty);}}
}
int main(void)
{int n,m;cin >> n >> m;vector<vector<int>> grid(n,vector<int>(m,0));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin >> grid[i][j];}}vector<vector<bool>> firstorder(n,vector<bool>(m,false));vector<vector<bool>> secondorder(n,vector<bool>(m,false));for(int i=0;i<n;i++){dfs(grid,firstorder,i,0);dfs(grid,secondorder,i,m-1);}for(int j=0;j<m;j++){dfs(grid,firstorder,0,j);dfs(grid,secondorder,n-1,j);}for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(firstorder[i][j]==true && secondorder[i][j]==true){cout << i << " " << j << endl;}}}return 0;
}
  • 本方法是从边界逆向流水(从低到高),将从边界能流到的地方做一个标记(左上一个,右下一个),当一个点既能被第一组边界流到,也能被第二组边界流到,那么该点符合题意,直接输出
//直接dfs暴力法(更加耗时)
#include <iostream>
#include <vector>
using namespace std;
int n, m;
int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1};// 从 x,y 出发 把可以走的地方都标记上
void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y) {if (visited[x][y]) return;visited[x][y] = true;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= n || nexty < 0 || nexty >= m) continue;if (grid[x][y] < grid[nextx][nexty]) continue; // 高度不合适dfs (grid, visited, nextx, nexty);}return;
}
bool isResult(vector<vector<int>>& grid, int x, int y) {vector<vector<bool>> visited(n, vector<bool>(m, false));// 深搜,将x,y出发 能到的节点都标记上。dfs(grid, visited, x, y);bool isFirst = false;bool isSecond = false;// 以下就是判断x,y出发,是否到达第一组边界和第二组边界// 第一边界的上边for (int j = 0; j < m; j++) {if (visited[0][j]) {isFirst = true;break;}}// 第一边界的左边for (int i = 0; i < n; i++) {if (visited[i][0]) {isFirst = true;break;}}// 第二边界下边for (int j = 0; j < m; j++) {if (visited[n - 1][j]) {isSecond = true;break;}}// 第二边界右边for (int i = 0; i < n; i++) {if (visited[i][m - 1]) {isSecond = true;break;}}if (isFirst && isSecond) return true;return false;
}int main() {cin >> n >> m;vector<vector<int>> grid(n, vector<int>(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++) {for (int j = 0; j < m; j++) {if (isResult(grid, i, j)) {cout << i << " " << j << endl;}}}
}
  • 遍历图中所有的点,看看从这里能不能同时到达两组边界,dfs是将从当前点出发,将可以走到的位置全部标记,然后通过isResult函数看看两组边界有没有被标记,若都标记了,那这一点就可以到达边界,就输出位置,每次调用isResult函数都会重新创建一个visited数组
http://www.zskr.cn/news/1371592.html

相关文章:

  • 【太阳能】PEM电解模拟了24小时太阳能绿色氢电厂(每小时太阳能发电量、氢气产量、用水量、储罐动态以及每公斤H₂的成本【含Matlab源码 15561期】
  • ODM终极指南:5步快速上手免费开源无人机影像处理,生成专业三维模型与正射影像
  • 审核员职业选择:外审还是内审? - 众智商学院职业教育
  • 帆软市场部为什么能成为高人效增长系统?
  • 本地回收行业优质代表,重庆诚鑫名品稳居榜单前列 - 诚鑫名品
  • 为团队项目统一配置Taotoken的Token Plan套餐以优化成本
  • 混沌系统预测方法全景评测:从线性回归到神经ODE的实战指南
  • 量子机器学习在金融领域的应用:从核心算法到图神经网络实践
  • 矩阵补全与因果推断:评估贸易协定效应的前沿方法与实践
  • 量子机器学习对抗鲁棒性:模型无关的理论下界计算与评估
  • 22. LangChain LCEL,用 | 串联AI的魔法语言
  • 深度解析sguard_limit:ACE-Guard内核级资源限制器的架构设计与性能优化
  • DeepSeek企业私有化部署隐私加固手册(含密钥轮转SOP、审计日志留存策略、跨境传输断点协议)
  • 终极解决方案:Applite如何彻底改变macOS应用管理体验
  • AllData数据中台架构解析与部署实战:企业级数据治理平台技术深度指南
  • 告别U盘!用EasyBCD在Win11上无损硬盘安装Ubuntu 22.04保姆级教程
  • 使用Taotoken稳定调用大模型API提升智能客服响应效率
  • Gofile极速下载器:3倍下载速度的完整指南
  • 3步突破格式限制:网易云音乐NCM文件转换终极指南
  • League-Toolkit:英雄联盟玩家的智能自动化助手终极指南
  • 前端自定义右键菜单
  • XCOM 2模组管理终极方案:AML启动器完全手册
  • 华为OD机试真题 新系统 Java实现 【数据包优先级窗口查找】
  • 机器学习泛化理论:从AIC/BIC到集中不等式的模型选择与误差分析
  • 从岭回归到Lasso:正则化原理、稀疏性与ADMM算法实践
  • 量化精度损失超8.7%?DeepSeek-VL多模态模型INT4部署避坑指南,含Per-Tensor校准实操清单
  • 数据决定上限,准备决定成败:DeepSeek同源训练数据预处理全链路拆解,错过这3个关键阈值=白训2000卡时
  • 紧急通告:Gemini当前版本对非RGB图像(CMYK/灰度/16bit TIFF)存在系统性解析缺陷!已确认影响金融票据识别与工业质检部署,补丁预计Q3上线
  • WorkshopDL终极指南:跨平台Steam创意工坊模组自由下载神器
  • PolyPyGY二维碳材料:计算设计的高性能锂电阳极新星