- Definition:
0. use a 2d array of integers to represent a maze;
1. 0 for passable, 1 if not;
2. the first element (maze[0][0]) is the entry;
3. the last element (maze[maze.length - 1][maze[maze.length - 1].length - 1]) is the exit;
eg.
0, 1, 1
1, 0, 1
1, 1, 0
4. horizontal, vertical and diagonal moves are allowed;
- Question:
Find out all the possible ways out and figure out the shortest one.
- Solution:
0. start from the entry point of the maze, define and initialize three pointers: previous, current and next;
1. search all passable points next to current point and store them in a linked list;
2. remove one from the passable list as next, point previous to current and point current to next, then push the rest passables into a stack for later backtracking;
3. if no more passable point is found at the current position, pop one point from the stack, go back to the right place and choose a different move;
4. wrap 1-3 in a loop until all paths of the maze are searched.
- Codes:
0. MazeSearcher
package co.speedar.dsal.maze; import java.util.LinkedList; import java.util.List; import java.util.Stack; /** * Search all the ways out in a given maze. * * @author ben * @creation 2014年4月13日 */ public class MazeSearcher { /** * 2d integer matrix, representing the maze.<br/> * Definition: <br/> * 1. 0 for passable, 1 if not;<br/> * 2. the first element (maze[0][0]) is the entry;<br/> * 3. the last element (maze[maze.length - 1][maze[maze.length - 1].length - 1]) is the exit;<br/> * eg.<br/> * 0, 1, 1<br/> * 1, 0, 1<br/> * 1, 1, 0<br/> */ private int[][] maze; /** * current search trunk<br/> * {currentLoc,preLoc} */ private List<Point[]> currentPath = new LinkedList<Point[]>(); /** * holds candidate movables, used for backtracking<br/> * {currentLoc,preLoc,nextLoc} */ private Stack<Point[]> stack = new Stack<Point[]>(); /** * holds all the solutions. */ private List<List<Point[]>> paths = new LinkedList<List<Point[]>>(); public MazeSearcher(int[][] maze) { super(); this.maze = maze; } /** * find out all the possible paths */ public void searchAllPaths() { Point current = new Point(0, 0); Point pre = null; Point next = null; // add the start point currentPath.add(new Point[] { current, pre }); List<Point> movables = searchNext(current, pre); do { if (movables != null && !movables.isEmpty()) { // still movable next = movables.remove(0); if (movables != null && !movables.isEmpty()) { // has optional paths, push them into the stack for backtracking for (int i = 0; i < movables.size(); i++) { // {current position, pre position, next position} Point temPoint = movables.remove(0); System.out.println("stack.push: " + "{" + current + "," + pre + "," + temPoint + "}"); stack.push(new Point[] { current, pre, temPoint }); } } pre = current; current = next; currentPath.add(new Point[] { current, pre }); next = null; } else { // backtrack if (!stack.isEmpty() && !currentPath.isEmpty()) { Point[] backtrackPoints = stack.pop(); System.out.println("stack.pop: " + "{" + backtrackPoints[0] + "," + backtrackPoints[1] + "," + backtrackPoints[2] + "}"); Point[] currentPathPoints; while (!currentPath.isEmpty()) { currentPathPoints = currentPath.remove(currentPath .size() - 1); if (currentPathPoints[0].equals(backtrackPoints[0]) && ((currentPathPoints[1] == null && backtrackPoints[1] == null) || currentPathPoints[1] .equals(backtrackPoints[1]))) { // track back to the right position currentPath.add(currentPathPoints); break; } } // choose a different position at that point next = backtrackPoints[2]; pre = backtrackPoints[1]; current = backtrackPoints[0]; pre = current; current = next; currentPath.add(new Point[] { current, pre }); next = null; } } // check and save path if exit if (isExit(current)) { rememberCurrentPath(); } // search next movables movables = searchNext(current, pre); // print out current path printCurrentPath(); } while ((movables != null && !movables.isEmpty()) || !stack.isEmpty()); // continue loop if still movable or backtrackable } public void printCurrentPath() { for (Point[] currentPoints : currentPath) { System.out.print(currentPoints[0] + " -> "); } if (isExit(currentPath.get(currentPath.size() - 1)[0])) { System.out.print("end"); System.out.println(); System.out.println("a way out found!"); } else { System.out.println(); } } public void printShortestPath() { int shortestLength = paths.get(0).size(); List<Point[]> shortestPath = paths.get(0); for (List<Point[]> tempPath : paths) { if (tempPath.size() < shortestLength) { shortestLength = tempPath.size(); shortestPath = tempPath; } } System.out.println("The shortest path is: "); for (Point[] currentPoints : shortestPath) { System.out.print(currentPoints[0] + " -> "); } System.out.println("end"); } public void printAllPaths() { System.out.println("Here are all the ways out: "); for (List<Point[]> currentPoints : paths) { for (Point[] points : currentPoints) { System.out.print(points[0] + " -> "); } System.out.println("end"); } } private void rememberCurrentPath() { List<Point[]> currentPoints = new LinkedList<Point[]>(); for (Point[] points : currentPath) { currentPoints.add(points); } paths.add(currentPoints); } /** * the current point is exit or not * * @param current * @return */ private boolean isExit(Point current) { if (maze.length - 1 == current.x && maze[maze.length - 1].length - 1 == current.y && isAvailable(current)) { return true; } return false; } /** * search all next movable positions<br/> * * @param current * @param pre * @return */ private List<Point> searchNext(Point current, Point pre) { Point next = null; List<Point> movables = new LinkedList<Point>(); if (isExit(current)) { return movables; } next = searchNorth(current); checkAndSaveNext(current, pre, next, movables); next = searchNorthEast(current); checkAndSaveNext(current, pre, next, movables); next = searchEast(current); checkAndSaveNext(current, pre, next, movables); next = searchSouthEast(current); checkAndSaveNext(current, pre, next, movables); next = searchSouth(current); checkAndSaveNext(current, pre, next, movables); next = searchSouthWest(current); checkAndSaveNext(current, pre, next, movables); next = searchWest(current); checkAndSaveNext(current, pre, next, movables); next = searchNorthWest(current); checkAndSaveNext(current, pre, next, movables); return movables; } /** * 1.check if null;<br/> * 2.check if available;<br/> * 3.check if duplicated to previous;<br/> * 4.check if circled; * * @param current * @param pre * @param next * @param movables */ private void checkAndSaveNext(Point current, Point pre, Point next, List<Point> movables) { if (next != null && isAvailable(next) && !next.equals(pre) && !containsCircle(next)) { movables.add(next); } } private boolean containsCircle(Point next) { for (Point[] path : currentPath) { if (path[0].equals(next)) { return true; } } return false; } private boolean isAvailable(Point next) { if (maze[next.x][next.y] == 0) { return true; } return false; } private Point searchNorthWest(Point current) { Point next = null; if (current.x - 1 >= 0 && current.y - 1 >= 0) { next = new Point(current.x - 1, current.y - 1); } return next; } private Point searchWest(Point current) { Point next = null; if (current.y - 1 >= 0) { next = new Point(current.x, current.y - 1); } return next; } private Point searchSouthWest(Point current) { Point next = null; if (current.x + 1 < maze.length && current.y - 1 >= 0) { next = new Point(current.x + 1, current.y - 1); } return next; } private Point searchSouth(Point current) { Point next = null; if (current.x + 1 < maze.length) { next = new Point(current.x + 1, current.y); } return next; } private Point searchSouthEast(Point current) { Point next = null; if (current.x + 1 < maze.length && current.y + 1 < maze[current.x + 1].length) { next = new Point(current.x + 1, current.y + 1); } return next; } private Point searchEast(Point current) { Point next = null; if (current.y + 1 < maze[current.x].length) { next = new Point(current.x, current.y + 1); } return next; } private Point searchNorthEast(Point current) { Point next = null; if (current.x - 1 >= 0 && current.y + 1 < maze[current.x - 1].length) { next = new Point(current.x - 1, current.y + 1); } return next; } private Point searchNorth(Point current) { Point next = null; if (current.x - 1 >= 0) { next = new Point(current.x - 1, current.y); } return next; } }
1. Point
package co.speedar.dsal.maze; /** * Simulates a point in the maze. * * @author ben * @creation 2014年4月14日 */ public class Point { /** * row index */ int x; /** * column index */ int y; Point(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object obj) { if (obj instanceof Point) { Point that = (Point) obj; if (this.x == that.x && this.y == that.y) { return true; } } return false; } @Override public String toString() { return "(" + this.x + "," + this.y + ")"; } }
2. MazeSearcherTest
/** * */ package co.speedar.dsal.maze; /** * @author ben * @creation 2014年4月14日 */ public class MazeSearcherTest { /** * @param args */ public static void main(String[] args) { int[][] maze = new int[4][4]; int[] tempInts; tempInts = new int[] { 0, 0, 1, 1 }; maze[0] = tempInts; tempInts = new int[] { 1, 1, 0, 1 }; maze[1] = tempInts; tempInts = new int[] { 1, 0, 1, 0 }; maze[2] = tempInts; tempInts = new int[] { 0, 1, 0, 0 }; maze[3] = tempInts; MazeSearcher searcher = new MazeSearcher(maze); searcher.searchAllPaths(); searcher.printAllPaths(); searcher.printShortestPath(); } }
- Test Result:
(0,0) -> (0,1) -> (0,0) -> (0,1) -> (1,2) -> stack.push: {(1,2),(0,1),(2,1)} (0,0) -> (0,1) -> (1,2) -> (2,3) -> stack.push: {(2,3),(1,2),(3,2)} (0,0) -> (0,1) -> (1,2) -> (2,3) -> (3,3) -> end a way out found! stack.pop: {(2,3),(1,2),(3,2)} (0,0) -> (0,1) -> (1,2) -> (2,3) -> (3,2) -> stack.push: {(3,2),(2,3),(2,1)} (0,0) -> (0,1) -> (1,2) -> (2,3) -> (3,2) -> (3,3) -> end a way out found! stack.pop: {(3,2),(2,3),(2,1)} (0,0) -> (0,1) -> (1,2) -> (2,3) -> (3,2) -> (2,1) -> (0,0) -> (0,1) -> (1,2) -> (2,3) -> (3,2) -> (2,1) -> (3,0) -> stack.pop: {(1,2),(0,1),(2,1)} (0,0) -> (0,1) -> (1,2) -> (2,1) -> stack.push: {(2,1),(1,2),(3,0)} (0,0) -> (0,1) -> (1,2) -> (2,1) -> (3,2) -> stack.push: {(3,2),(2,1),(3,3)} (0,0) -> (0,1) -> (1,2) -> (2,1) -> (3,2) -> (2,3) -> (0,0) -> (0,1) -> (1,2) -> (2,1) -> (3,2) -> (2,3) -> (3,3) -> end a way out found! stack.pop: {(3,2),(2,1),(3,3)} (0,0) -> (0,1) -> (1,2) -> (2,1) -> (3,2) -> (3,3) -> end a way out found! stack.pop: {(2,1),(1,2),(3,0)} (0,0) -> (0,1) -> (1,2) -> (2,1) -> (3,0) -> Here are all the ways out: (0,0) -> (0,1) -> (1,2) -> (2,3) -> (3,3) -> end (0,0) -> (0,1) -> (1,2) -> (2,3) -> (3,2) -> (3,3) -> end (0,0) -> (0,1) -> (1,2) -> (2,1) -> (3,2) -> (2,3) -> (3,3) -> end (0,0) -> (0,1) -> (1,2) -> (2,1) -> (3,2) -> (3,3) -> end The shortest path is: (0,0) -> (0,1) -> (1,2) -> (2,3) -> (3,3) -> end
相关推荐
Nessus-5.0.2-适用于BackTrack的版本
回溯算法0-1背包问题代码实现。算法backtrack在最坏情况下可能需要更新当前最优解O(n-1)!)次,每次更新bestx需计算时间O(n),从而整个算法的计算时间复杂性为O(n!)。
Backtrack无线攻防步步为营 Backtrack 5 R3 is a notorious Digital Forensic and Intrusion Detection software bundle with a whole lot of tools for Penetration Testing, It is based on Linux and includes ...
回溯算法旅行商问题代码实现。算法backtrack在最坏情况下可能需要更新当前最优解O(n-1)!)次,每次更新bestx需计算时间O(n),从而整个算法的计算时间复杂性为O(n!)。
#update-alternatives --install /usr/bin/java java /opt/java/jre1.7.0_05/bin/java 1 #update-alternatives --set java /opt/java/jre1.7.0_05/bin/java #mkdir -p /root/.mozilla/plugins #ln -sf /opt/java/jre...
@ backtrack / preset-git-hooks 关于 预设,通过添加git hooks。 特征 添加git钩子 安装 npm install --save-dev @backtrack/preset-git-hooks 用法 // backtrack.config.js 'use strict' ; module . exports = { ...
回溯数独使用回溯算法的数独求解器该项目该应用程序允许用户尝试解决各种大小和难度的数独难题。 它包含一个内置的求解器,可以使用递归回溯算法快速解决任何大小的难题。 用户可以尝试解决难题并检查其解决方案,...
本文实例讲述了Python基于回溯法解决01背包问题。分享给大家供大家参考,具体如下: 同样的01背包问题,前面采用动态规划的方法,现在用回溯法解决。回溯法采用深度优先策略搜索问题的解,不多说,代码如下: bestV...
void color::backtrack(int t) { if(t>n){ sum++; cout(4); for(int i=1;i;i++) cout[i]; cout; } else for(int i=1;i;i++){ x[t]=i; if(ok(t)) backtrack(t+1); } }
BackTrack-4-Assuring-Security-by-Penetration-Testing英文版
制作可保存配置的U盘版BT4(BackTrack4).docx 一、安装 1、准备: 1).最小的USB驱动器的容量4GB的USB,格式为FAT32的; 2).BT4正式版: 下载地址:[url]http://www.remote-exploit.org/backtrack_download.html[/url] ...
关于如何在VirtualBox中安装BackTrack3的图解说明。
ZerOne无线安全教程B--BackTrack2 Linux下破解无线WPA-PSK加密
用回溯法解0_1背包问题时,会用到状态空间树。在搜索状态空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。当右子树有可能包含最优解时才进入右子树搜索,否则将右子树剪去。设r是当前剩余物品价值...
基于BackTrack5的渗透测试教程,内容详细。
回溯使用具有回溯算法的golang代码重用进行实验。 您可以在阅读有关该过程的更多信息。
Backtrack 5 R1 的两个32位iso种子,KDE-32 和 gnome-32 自己找了好久,算是备份一下,下次下载的时候好找
backtrack 渗透系统全系列教程种子
A063-网络设备安全-通过BackTrack5渗透测试工具实现Ethernet协议渗透测试 A064-网络设备安全-通过Scapy实现IEEE802.1Q渗透测试 A065-网络设备安全-通过BackTrack5渗透测试工具进行ARP协议渗透测试 A066-网络设备安全...