迷宫问题一般可以建模为一个二维数组,二维数组的值表示位置(i,j)是否可以通行,将位置数据结构设为
每个格网的数据结构
public class Loc { int row_idx; int col_idx; Loc pre; boolean pass; boolean visited; public Loc(int i,int j,Loc pre,boolean pass,boolean visited) { this.row_idx=i; this.col_idx=j; this.pre=pre;//记录该路径的前驱,以便记录整条路径 this.pass=pass; this.visited=visited;//是否被访问过 } //确认位置loc和this的位置是否一样(包含引用相同和深拷贝相同两种) public boolean equals(Loc loc) { if(this.row_idx==loc.row_idx && this.col_idx==loc.col_idx) return true; else return false; } //位置输出 public String toString() { return "("+this.row_idx+","+this.col_idx+")"; }
整个迷宫数据结构:
public class Maze { Loc[][] maze; //迷宫类构造函数,用二维数组初始化一个迷宫 public Maze(int[][] nums) { int len1=nums.length; int len2=nums[0].length; this.maze=new Loc[len1][len2]; for(int i=0;i<len1;i++) { for(int j=0;j<len2;j++) { if(nums[i][j]==1) this.maze[i][j]=new Loc(i,j,null,true,false); else this.maze[i][j]=new Loc(i,j,null,false,false); } } } //判断位置是否在迷宫内部 public boolean inMaze(int row_idx,int col_idx) { int rows=this.maze.length; int cols=this.maze[0].length; if(row_idx>=0 && row_idx<rows && col_idx>=0 && col_idx<cols) return true; else return false; }
public String Route2String(Loc end) { Loc p=end; String route=""; while(p!=null) { route=p.toString()+route; p=p.pre; } return "路线为:"+route; }
使用深度优先搜索和广度优先搜索都可以求解,深度优先搜索就像一条蛇在迷宫中搜索,一直向前试探如果前路不通则后退一格,从当前格子的其他方向再进行搜索。广度优先搜索相当于小虫子在迷宫中走,每次遇到一个岔路口就分身,有几条岔路就分成几个虫子继续向前。
栈实现的深度优先搜索:
public Loc DFS_route(Loc start,Loc end) { int[][] dirs={{-1,0},{1,0},{0,-1},{0,1}}; LinkedStack<Loc> stack=new LinkedStack<Loc>(); stack.push(start); start.visited=true; while(!stack.isEmpty()) { Loc temp=stack.pop(); for(int dir=0;dir<4;dir++) { int new_r=temp.row_idx+dirs[dir][0]; int new_c=temp.col_idx+dirs[dir][1]; if( this.inMaze(new_r,new_c) && !this.maze[new_r][new_c].visited && this.maze[new_r][new_c].pass) { stack.push(this.maze[new_r][new_c]); this.maze[new_r][new_c].visited=true; this.maze[new_r][new_c].pre=temp; if(this.maze[new_r][new_c].equals(end)) return end; } } } return null;
队列实现的广度优先搜索:
public Loc BFS_route(Loc start,Loc end) { int[][] dirs={{-1,0},{1,0},{0,-1},{0,1}}; LinkedQueue<Loc> q=new LinkedQueue<Loc>(); q.enqueue(start); start.visited=true; while(!q.isEmpty()) { Loc temp=q.dequeu(); for(int dir=0;dir<4;dir++) { int new_r=temp.row_idx+dirs[dir][0]; int new_c=temp.col_idx+dirs[dir][1]; if( this.inMaze(new_r,new_c) && !this.maze[new_r][new_c].visited && this.maze[new_r][new_c].pass) { q.enqueue(this.maze[new_r][new_c]); this.maze[new_r][new_c].visited=true; this.maze[new_r][new_c].pre=temp; if(this.maze[new_r][new_c].equals(end)) return end; } } } return null; }
测试程序:
public static void main(String[] args) { // TODO Auto-generated method stub int[][] nums={{1,1,1,0,0,1,1},{1,1,1,0,0,1,0},{0,0,1,0,0,1,0},{1,1,1,1,1,1,0}, {0,1,0,0,0,1,0},{1,1,0,0,0,0,1},{1,1,1,1,1,1,1}}; Maze m=new Maze(nums); Loc start=m.maze[0][0]; Loc end=m.maze[6][6]; System.out.println(m.Route2String(m.DFS_route(start,end))); Maze n=new Maze(nums); start=n.maze[0][0]; end=n.maze[6][6]; Loc e=n.BFS_route(start,end); System.out.println(m.Route2String(e)); System.out.println(); }
输出:
路线为:(0,0)(1,0)(1,1)(1,2)(2,2)(3,2)(3,1)(4,1)(5,1)(6,1)(6,2)(6,3)(6,4)(6,5)(6,6)