二叉树 迷宫问题

来源:互联网 发布:天下足球 知乎 编辑:程序博客网 时间:2024/04/18 22:31
定义一个二维数组N*M(其中2<=N<=8;2<=M<=8),如5 × 5数组下所示: 
int maze[5][5] = {
        0, 0, 0, 
        1, 1, 0, 
        1, 1, 0, 
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。入口点为[0,0],既第一空格是可以走的路。
Input
一个N × M的二维数组,表示一个迷宫。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
Sample Input
0 0 0 
1 1 0 
1 1 0
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Output
(0, 0)  (1, 0)  (2, 0)  (2, 1)  (2, 2) 

三种方法:

方法一:

package work;


import java.util.Scanner;
import java.util.Stack;


/**
 *
使用栈实现深度优先遍历,类似于二叉树的先序遍历
 * @author 建
 *
 */
public class Work2_migong {


public static Stack<Point> stk = new Stack<>();// 队列,用来保存走通的点的坐标


public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("请输入行数:");
while (in.hasNext()) {
int maxrow = in.nextInt();
System.out.println("行数:" + maxrow);
System.out.println("请输入列数:");
int maxclo = in.nextInt();
System.out.println("列数:" + maxclo);
int[][] maze = new int[maxrow][maxclo];
System.out.println("建立迷宫!");
for (int i = 0; i < maze.length; i++) { // 迷宫的建立
for (int j = 0; j < maze[i].length; j++) {
System.out.println("请输入点(" + i + "," + j +")的值:");
maze[i][j] = in.nextInt();
}
}
Point p = new Point(0, 0, null);// 起点
System.out.println("起点0,0已经放进记录路径的栈。");
stk.push(p);
System.out.println("程序开始自动寻路!");
System.out.println("栈是否不为空?" + !stk.isEmpty());
while (!stk.isEmpty()) {
p = (Point) stk.pop();
if (p.x == maxrow - 1 && p.y == maxclo - 1) {
System.out.println("到达终点!");
break;// 如果达到maze[maxrow - 1][maxclo - 1] 表示达到终点,直接break
}
if (p.x + 1 < maxrow && maze[p.x + 1][p.y] == 0){// 向下走一步
System.out.println("横坐标加1小于最大行数,并且当前点的下面的那个点的值是0,向下走一步!");
visit(p.x + 1, p.y, p);
System.out.println("已经把刚刚走的点(" + (p.x + 1) + "," + p.y + ")加入了路径的栈中");
}
if (p.y + 1 < maxclo && maze[p.x][p.y + 1] == 0){// 向右走一步
System.out.println("纵坐标加1小于最大列数,并且当前点的右面的那个点的值是0,向右走一步!");
visit(p.x, p.y + 1, p);
System.out.println("已经把刚刚走的点(" + p.x + "," + (p.y+1) + ")加入了路径的栈中");
}
}
Stack<Point> stack = new Stack<>();// 栈 来存储走通的路径
//存储的是最后走的那个点。。
stack.push(p);
while (p.ptrPoint != null) {
p = p.ptrPoint;
stack.push(p);
}
System.out.println("打印走通的路径:");
while (!stack.isEmpty())// 打印路径,因为坐标点已经重写了toString方法
System.out.println(stack.pop());
}
in.close();
}


public static void visit(int x, int y, Point pre) {
Point visitedPoint = new Point(x, y, pre);
// 后一个节点对前一个节点的引用存在,不会被GC回收,!!!!!!!
stk.push(visitedPoint);
System.out.println(stk.size());

}
}


方法二:

package work;


import java.util.ArrayList;
import java.util.Scanner;




/**
 * * 迷宫问题:
递归,类似动态规划,将问题拆解
* @author 建
 *
 */
public class work3_migng {


public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int row = sc.nextInt();
            int col = sc.nextInt();
            int[][] matrix = new int[row][col];
            ArrayList<Integer> list = new ArrayList<>();
            for (int i = 0; i < row; i++) {
                for (int j = 0; j < col; j++){
                System.out.println("请输入(" + i + "," + j + ")的值:");
                    matrix[i][j] = sc.nextInt();
                }
            }
            search(matrix, list, row - 1, col - 1);
        }
        sc.close();
    }

public static void search(int[][] matrix, ArrayList<Integer> list1, int row, int col) {
        if(row<0 || col<0)    // 超出了迷宫范围
            return;
        if(matrix[row][col] == 1)  // 不允许走
            return;
// 记录路线
        list1.add(col);
        list1.add(row);


        // 走到了出发点
        if (row == 0 && col == 0) {
            for (int i = list1.size() - 1; i >= 0; i--) {
                System.out.println("(" + list1.get(i) + "," + list1.get(--i) + ")");
            }
            return;
        }


        // 递归
        search(matrix, list1, row-1, col);
        search(matrix, list1, row, col-1);
    }
}

方法三:

package work;


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


/**
 *  迷宫问题:
使用队列实现广度优先遍历,类似于二叉树的层序遍历
 * @author 建
 *
 */
public class Work4_migong {


public static Queue<Point> queue = new LinkedList<>();// 队列,用来保存走通的点的坐标


    public static void visit(int x, int y, Point pre, int[][] maze) {
        Point visitedPoint = new Point(x, y, pre);
        // 后一个节点对前一个节点的引用存在,不会被GC回收,!!!!!!!
        queue.offer(visitedPoint);
    }


    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int maxrow = in.nextInt();
            int maxclo = in.nextInt();
            int[][] maze = new int[maxrow][maxclo];
            for (int i = 0; i < maze.length; i++) { // 迷宫的建立
                for (int j = 0; j < maze[i].length; j++) {
                System.out.println("请输入点(" + i + "," + j +")的值:");
                    maze[i][j] = in.nextInt();
                }
            }
            Point p = new Point(0, 0, null);// 起点
            queue.offer(p);
            while (!queue.isEmpty()) {
                p = queue.poll();
                if (p.x == maxrow - 1 && p.y == maxclo - 1) {
                    break;// 如果达到maze[maxrow - 1][maxclo - 1] 表示达到终点,直接break
                }
                if (p.x + 1 < maxrow && maze[p.x + 1][p.y] == 0)// 向下走一步
                    visit(p.x + 1, p.y, p, maze);
                if (p.y + 1 < maxclo && maze[p.x][p.y + 1] == 0)// 向右走一步
                    visit(p.x, p.y + 1, p, maze);
            }
            Stack<Point> stack = new Stack<>();// 栈 来存储走通的路径
            stack.push(p);
            while (p.ptrPoint != null) {
                p = p.ptrPoint;
                stack.push(p);
            }
            while (!stack.isEmpty())// 打印路径,因为坐标点已经重写了toString方法
                System.out.println(stack.pop());
        }
        in.close();
    }
}