1. 程式人生 > >深度優先和廣度優先遍歷迷宮

深度優先和廣度優先遍歷迷宮

package didi;

import java.util.Stack;

/**
 * 深度優先迷宮問題
{{1,1,0,1},
{1,1,0,1},
{0,1,1,1},
{0,0,1,1}};

{1,1,1,0,1},
{1,0,1,0,1},
{1,0,1,1,1},
{1,1,0,1,1},
{0,0,0,1,1},
 * @author yanjie
 *
 */
public class DFPath {

    public static void main(String[] args) {
    	//迷宮點,1表示可走,0表示不可走,(0,0)為入口,(0,3)為出口
        int[][] maze = {{1,1,1,0,1},
		        		{1,0,1,0,1},
		        		{1,0,1,1,1},
		        		{1,1,0,1,1},
		        		{0,0,0,1,1}};
        //可以走的方向,上下左右
        int[][] move = {{0,-1},{0,1},{-1,0},{1,0}};
        //使用棧s儲存路徑
        Stack<Point> s = new Stack<Point>();
        int a = path(maze, move, s);
        if(a==1){
        	while(!s.isEmpty()){//輸出是倒的
            	Point step = s.pop();
                System.out.println(step.x+" "+step.y);
            }
        }
    }
    /**
     * 將(0,0)點入棧,將maze[0][0]=-1,表示點(0,0)已經訪問過了
     * 維護一個當前點temp,第一次temp為棧頂,判斷temp其周圍四個點是否可達,
     * 如果可達則將temp更新為可達的那個點,並將maze路徑中對應位置標記位-1,表示已經訪問過
     * 如果不可達則彈出棧頂,取棧下一個元素
     * 當stack不為空時
     * @param maze
     * @param move
     * @param s
     * @return
     */
    public static int path(int[][] maze,int[][] move,Stack<Point> s){
    	Point temp = new Point(0,0); //起點
    	maze[0][0]=-1;//表示已經訪問過這個點了
    	int m=maze.length-1,n=maze[0].length-1;
        s.push(temp);
        //棧不為空
        while(!s.isEmpty()){
        	//取棧頂的點
            temp = s.peek();
            int d = 0;
            //遍歷上下左右四個方向
            while(d<4){
                int i = temp.x + move[d][0];
                int j = temp.y + move[d][1];
                //該點不越界,且可達
                if(i>=0 && j>=0 && i<=m && j<=n && maze[i][j]==1){
                    temp = new Point(i,j); //到達新點
                    s.push(temp);
                    maze[i][j] = -1;  //到達新點,標誌已經到達
                    if(i == 0 && j == n){
                        return 1;  //到達出口,迷宮有路,返回1
                    }else{
                        d = 0;  //此時temp點已經更新為新點了,重新初始化方向
                    }
                }else{
                    d++; //改變方向
                }
            }
            //遍歷其周圍四個點,都沒法通過,則彈出這個點
            s.pop();
        }
        return 0;
    }
    static class Point{
        int x,y;
        public Point(int x,int y) {
            this.x = x;//橫座標
            this.y = y;//縱座標
        }
    }
}
package didi;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

/**
 * 廣度優先求解迷宮問題
{{1,1,0,1},
{1,1,0,1},
{0,1,1,1},
{0,0,1,1}};

{1,1,1,0,1},
{1,0,1,0,1},
{1,0,1,1,1},
{1,1,0,1,1},
{0,0,0,1,1},
 * @author yanjie
 *
 */
public class BFPath {

    public static void main(String[] args) {
    	//迷宮點,1表示可走,0表示不可走,(0,0)為入口,(0,3)為出口
        int[][] maze = {{1,1,1,0,1},
		        		{1,0,1,0,1},
		        		{1,0,1,1,1},
		        		{1,1,0,1,1},
		        		{0,0,0,1,1}};
        //可以走的方向,上下左右
        int[][] move = {{0,-1},{0,1},{-1,0},{1,0}};
        //使用佇列s儲存路徑
        
        path(maze, move);
    }
    /**
     * 將(0,0)點入棧,將maze[0][0]=-1,表示點(0,0)已經訪問過了
     * 維護一個當前點temp,第一次temp為棧頂,判斷temp其周圍四個點是否可達,
     * 如果可達則將temp更新為可達的那個點,並將maze路徑中對應位置標記位-1,表示已經訪問過
     * 如果不可達則彈出棧頂,取棧下一個元素
     * 當stack不為空時
     * @param maze
     * @param move
     * @param s
     * @return
     */
    public static void path(int[][] maze,int[][] move){
    	Queue<Point> q = new LinkedList<Point>();
    	q.add(new Point(0,0,null));
    	maze[0][0]=-1;//表示已經訪問過這個點了
    	int m=maze.length-1,n=maze[0].length-1;
        
        //佇列不為空
        while(!q.isEmpty()){
        	//出隊
        	Point temp = q.poll();
            int x = temp.x;
            int y = temp.y;
            int d = 0;//
            while(d<4){
                int i = x + move[d][0];
                int j = y + move[d][1];
                //該點不越界,且可達
                if(i>=0 && j>=0 && i<=m && j<=n && maze[i][j]==1){
                	Point point = new Point(i,j,temp); //新節點指向temp
                	if(x==1 && y==4){
                		System.out.println(i+"+"+j);
                	}
                    q.add(point);
                    maze[i][j] = -1;  //到達新點,標誌已經到達
                    
                    if(x == 0 && y == n){
                    	//到達出口,迷宮有路,沿著當前節點往前找
                    	System.out.println("找到!");
                    	Point cur = temp;
                    	while(cur!=null){
                    		System.out.println(cur.x+" "+cur.y);
                    		cur = cur.pre;
                    	}
                    }
                }else{
                    d++; //改變方向
                }
            }
        }
    }
    static class Point{
        int x,y;
        Point pre;//前驅節點
        public Point(int x,int y,Point pre) {
            this.x = x;//橫座標
            this.y = y;//縱座標
            this.pre = pre;//前驅節點
        }
    }
}