深度优先搜索:能否走出迷宫
来源:互联网 发布:c语言 max 头文件 编辑:程序博客网 时间:2024/05/27 14:14
题目
一个
- 测试输入
100 80
3
10 2 8 25
44 12 6 6
5 6 10 51 - 测试输出
1
分析
如果能走出迷宫,只需要找到其中的一条路径即可,所以适合用深度优先搜索。而广度优先搜索会去找所有路径中最短的,所以会在较大规模的迷宫中消耗较长的时间。
深度优先搜索在此问题中就是一种回溯法,具体思路是
1. 一旦搜索到一个可行点,立刻按照纵深方向搜索下一个可行点,如果这个点就是终点,则可以走出迷宫返回成功;
2. 每个可行点都要进行标记,保证之后不重复走已经标记的可行点;
3. 一旦发现当前点没有下一个可行点时,就从当前点退回到上一个可行点,从上一个可行点继续搜索可行点;
4. 如果上一个可行点仍然没有可行点,则一直退回直到某个最近点可以继续搜索可行点;
5. 如果一直退回到起点都不能搜索到下一个可行点,那么不能走出迷宫返回失败。
深度优先搜索可以使用递归的方式简单实现,而非递归的方式更能展现其搜索轨迹。非递归过程需要使用栈来保存搜索点,一旦搜索到可行点立刻入栈,并从此点纵深搜索下一个可行点;而如果没有下一个可行点,则当前点出栈,从上一个可行点继续搜索。
具体到本题,需要将激光经过的地方都标记为不可行点,然后按照深度优先搜索来寻找一条路径。但激光是一条直线不好表示为不可行点,我们可以将直线转化为一条向上凸起的折线,这样的折线只有两种形态,可见这样的转化并不会改变最后结果。
代码
import java.util.ArrayDeque;import java.util.Queue;import java.util.Scanner;import java.util.Stack;public class LaserMaze { static final int[][] MOVES = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};// 优先向右下方向前进 static class Pos { int x; int y; Pos(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object obj) { return ((Pos) obj).x == this.x && ((Pos) obj).y == this.y; } } // 广度优先搜索会超时 static int bfs(Pos start, Pos end, boolean[][] visited, int m, int n) { Queue<Pos> queue = new ArrayDeque<>(m * n); queue.add(start); Pos cur; while (!queue.isEmpty()) { cur = queue.remove(); if (cur.equals(end)) return 1; visited[cur.x][cur.y] = true; for (int[] step : MOVES) { int x = cur.x + step[0]; int y = cur.y + step[1]; if (x >= 0 && x <= n && y >= 0 && y <= m && !visited[x][y]) { Pos nextPos = new Pos(x, y); queue.add(nextPos); } } } return 0; } // 深度优先搜索递归实现 static int dfs(Pos cur, Pos end, boolean[][] visited, int m, int n) { if (cur.equals(end)) return 1;// 找到一条路径就返回 visited[cur.x][cur.y] = true;// 先对当前点标记,对已经走过的位置不重复走 for (int[] step : MOVES) { int x = cur.x + step[0]; int y = cur.y + step[1]; if (x >= 0 && x <= n && y >= 0 && y <= m && !visited[x][y]) { Pos next = new Pos(x, y); int ret = dfs(next, end, visited, m, n);// 对下一个可行点立刻纵深搜索 if (ret == 1) return 1;// 如果找到一条路径则立即返回,否则寻找下一个可行点 } } return 0; } // 深度优先搜索非递归实现 static int dfs2(Pos start, Pos end, boolean[][] visited, int m, int n) { Stack<Pos> stack = new Stack<>(); stack.push(start); visited[start.x][start.y] = true;// 入栈点立刻标记 Pos cur; boolean hasNext; while (!stack.isEmpty()) { cur = stack.peek(); if (cur.equals(end)) return 1;// 找到一条路径就返回 hasNext = false;// 有没有下一个可行点 for (int[] step : MOVES) { int x = cur.x + step[0]; int y = cur.y + step[1]; if (x >= 0 && x <= n && y >= 0 && y <= m && !visited[x][y]) { Pos next = new Pos(x, y); stack.push(next); visited[x][y] = true;// 入栈点立刻标记 hasNext = true; break;// 对找到的下一个可行点立刻纵向搜索 } } if (!hasNext) stack.pop();// 没有下一个可行点则当前点出栈 } return 0; } static void makeLaser(int[][] lasers, boolean[][] visited) { for (int[] aLaser : lasers) {// 保证折线是上凸的 if (aLaser[3] > aLaser[1]) { for (int i = aLaser[1]; i <= aLaser[3]; i++) { visited[aLaser[0]][i] = true; } for (int i = aLaser[0]; i <= aLaser[2]; i++) { visited[i][aLaser[3]] = true; } } else { for (int i = aLaser[0]; i <= aLaser[2]; i++) { visited[i][aLaser[3]] = true; } for (int i = aLaser[3]; i <= aLaser[1]; i++) { visited[aLaser[0]][i] = true; } } } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int m = sc.nextInt(); int n = sc.nextInt(); int nlaser = sc.nextInt(); int[][] lasers = new int[nlaser][4]; boolean[][] visited = new boolean[n + 1][m + 1]; for (int i = 0; i < nlaser; i++) { int x1 = sc.nextInt(); int y1 = sc.nextInt(); int x2 = sc.nextInt(); int y2 = sc.nextInt(); if (x1 < x2) {// 保证laser[0]<laser[2] lasers[i][0] = x1; lasers[i][1] = y1; lasers[i][2] = x2; lasers[i][3] = y2; } else { lasers[i][0] = x2; lasers[i][1] = y2; lasers[i][2] = x1; lasers[i][3] = y1; } } makeLaser(lasers, visited); Pos start = new Pos(0, 0); Pos end = new Pos(n, m); System.out.println(dfs(start, end, visited, m, n)); }}
0 0
- 深度优先搜索:能否走出迷宫
- 深度优先搜索生成迷宫
- C++广度优先搜索算法之走出迷宫
- HDU1269--迷宫城堡--深度优先搜索
- Matlab 深度优先搜索求解迷宫问题
- 深度优先搜索找迷宫的出路
- 深度优先搜索-求解迷宫解空间
- 用深度优先搜索解迷宫问题
- 深度优先搜索DFS(迷宫问题)
- DFS深度优先搜索之走迷宫
- 深度优先搜索——迷宫
- 深度优先搜索--迷宫可能路径--栈
- 走迷宫——深度优先搜索
- 深度优先搜索应用:走迷宫
- 深度优先搜索DFS 走迷宫
- 深度优先搜索求解迷宫问题
- dfs走迷宫_深度优先搜索
- 迷宫问题(深度优先搜索)
- MFC程序的执行顺序
- Selective Search for Object Recognition
- HDU
- C#键盘事件应用
- JVM调优总结(八)-典型配置举例2
- 深度优先搜索:能否走出迷宫
- UIWebView 与 JS 交互(1): stringByEvaluatingJavaScriptFromString方法的调用
- L1-046 整除光棍<高精度除低精度>
- MYSQL教程:查询篇
- Vijos 1104题:采药
- 一篇文章看懂ADAS
- Ubuntu下设置开机启动项
- Myeclipse2017中javaweb项目如何进入debug模式
- PHP程序员应当如何保持与时俱进?