首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

图论-水流问题

  • 25-02-16 04:00
  • 4215
  • 5221
blog.csdn.net

代码随想录笔记-水流问题

内容:

凡是涉及到水的问题, 基本上都离不开正向和逆向两方面

这道题也是如此.

将左边界和上边界视为第一边界,将右边界和下边界视为第二边界

每个格子的数值代表该位置的高度,水流只能流向等高和比该位置低的地方。

因此 输入

  1. 5 5
  2. 1 3 1 2 4
  3. 1 2 1 3 2
  4. 2 4 7 2 1
  5. 4 5 6 1 1
  6. 1 4 1 2 1

会输出

  1. 0 4
  2. 1 3
  3. 2 2
  4. 3 0
  5. 3 1
  6. 3 2
  7. 4 0
  8. 4 1

 如图

(图源自代码随想录官网)

题解1. (正向)流出

设置一个visited ,标记该格子可以流过的地方,之后再去检查边界部分的visited的值

该想法很直观,但是会带来一个时间复杂度很高的问题.

  1. import java.util.ArrayList;
  2. import java.util.Arrays;
  3. import java.util.List;
  4. import java.util.Scanner;
  5. /**
  6. * @author hasno
  7. */
  8. public class Main {
  9. static int[][] dir = {
  10. {1,0},{0,1},{-1,0},{0,-1}};
  11. //向下,向右,向上,向左
  12. public static void dfs(int[][] graph,int[][] visited,int x,int y) {
  13. if(visited[x][y] == 1) return;
  14. visited[x][y] = 1;
  15. for(int i = 0 ; i < 4 ; i++) {
  16. int nextx = x + dir[i][0];
  17. int nexty = y + dir[i][1];
  18. if(nexty < 0 || nextx < 0 || nextx >= graph.length || nexty >= graph[0].length) {
  19. continue;
  20. }
  21. if(graph[x][y] < graph[nextx][nexty] ) {
  22. continue;
  23. }
  24. dfs(graph,visited,nextx,nexty);
  25. }
  26. }
  27. public static boolean isResult(int[][] graph , int x , int y) {
  28. int[][] visited = new int[graph.length][graph[0].length];
  29. dfs(graph,visited,x,y);
  30. boolean isFirst = false;
  31. boolean isSecond = false;
  32. for(int i = 0 ; i < graph.length ; i++) {
  33. if (visited[i][0] == 1) {
  34. isFirst = true;
  35. break;
  36. }
  37. }
  38. for(int i = 0 ; i < graph[0].length ; i++) {
  39. if (visited[0][i] == 1) {
  40. isFirst = true;
  41. break;
  42. }
  43. }
  44. for(int i = 0 ; i < graph.length ; i++) {
  45. if (visited[i][graph[0].length-1] == 1) {
  46. isSecond = true;
  47. break;
  48. }
  49. }
  50. for(int i = 0 ; i < graph[0].length ; i++) {
  51. if (visited[graph.length-1][i] == 1) {
  52. isSecond = true;
  53. break;
  54. }
  55. }
  56. return isFirst && isSecond;
  57. }
  58. public static void main(String[] args) {
  59. Scanner scanner = new Scanner(System.in);
  60. //行数
  61. int n = scanner.nextInt();
  62. //列数
  63. int m = scanner.nextInt();
  64. int[][] graph = new int[n][m];
  65. for (int i = 0 ; i < n ; i++) {
  66. for(int j = 0 ; j < m ; j++) {
  67. graph[i][j] = scanner.nextInt();
  68. }
  69. }
  70. List> result = new ArrayList<>();
  71. for(int i = 0 ; i < n ; i++) {
  72. for(int j = 0 ; j < m ; j++) {
  73. if(isResult(graph,i,j)) {
  74. result.add(Arrays.asList(i,j));
  75. }
  76. }
  77. }
  78. for (List pri : result) {
  79. System.out.println(pri.get(0) + " " + pri.get(1));
  80. }
  81. }
  82. }

题解2. (逆向)逆流而上 

从边界开始往某一点去逆流而上。

检测条件: 必须要满足 本个比下一个小,才能标记下一个,否则无法标记

大体思路跟上面的区别不大,但是本质是以空间去换时间

记录两个边界逆流而上,看两个边界都能流到的点 即为满足条件的点

  1. import java.util.ArrayList;
  2. import java.util.Arrays;
  3. import java.util.List;
  4. import java.util.Scanner;
  5. /**
  6. * @author hasno
  7. */
  8. public class Main {
  9. static int[][] dir = {
  10. {1,0},{0,1},{-1,0},{0,-1}};
  11. //向下,向右,向上,向左
  12. public static void dfs(int[][] graph,int[][] visited,int x,int y) {
  13. if(visited[x][y] == 1) {
  14. return;
  15. }
  16. visited[x][y] = 1;
  17. for(int i = 0 ; i < 4 ; i++) {
  18. int nextx = x + dir[i][0];
  19. int nexty = y + dir[i][1];
  20. if(nexty < 0 || nextx < 0 || nextx >= graph.length || nexty >= graph[0].length) {
  21. continue;
  22. }
  23. if(graph[x][y] > graph[nextx][nexty] ) {
  24. continue;
  25. }
  26. dfs(graph,visited,nextx,nexty);
  27. }
  28. }
  29. public static void main(String[] args) {
  30. Scanner scanner = new Scanner(System.in);
  31. //行数
  32. int n = scanner.nextInt();
  33. //列数
  34. int m = scanner.nextInt();
  35. int[][] graph = new int[n][m];
  36. for (int i = 0 ; i < n ; i++) {
  37. for(int j = 0 ; j < m ; j++) {
  38. graph[i][j] = scanner.nextInt();
  39. }
  40. }
  41. int[][] firstBroder = new int[n][m];
  42. int[][] secondBroder = new int[n][m];
  43. //左右
  44. for(int i = 0 ; i < n ; i++) {
  45. dfs(graph,firstBroder,i,0);
  46. dfs(graph,secondBroder,i,m-1);
  47. }
  48. for(int i = 0 ; i < m ; i++) {
  49. dfs(graph,firstBroder,0,i);
  50. dfs(graph,secondBroder,n-1,i);
  51. }
  52. List> result = new ArrayList<>();
  53. for(int i = 0 ; i < n ; i++) {
  54. for(int j = 0 ; j < m ; j++) {
  55. if(firstBroder[i][j] == 1 && secondBroder[i][j] == 1) {
  56. result.add(Arrays.asList(i,j));
  57. }
  58. }
  59. }
  60. for (List pri : result) {
  61. System.out.println(pri.get(0) + " " + pri.get(1));
  62. }
  63. }
  64. }

总结:

遇到水流问题,正向&逆向都必须要考虑!

注:本文转载自blog.csdn.net的Hasno.的文章"https://blog.csdn.net/2301_79841192/article/details/145378445"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

137
数学
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top