迷宫问题

定义一个二维数组N*M(其中2<=N<=10;2<=M<=10),如5 × 5数组下所示:
int maze[5][5] = {

    0, 1, 0, 0, 0,

    0, 1, 0, 1, 0,

    0, 0, 0, 0, 0,

    0, 1, 1, 1, 0,

    0, 0, 0, 1, 0,

};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。入口点为[0,0],既第一空格是可以走的路。
Input
一个N × M的二维数组,表示一个迷宫。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

输入描述:
输入两个整数,分别表示二位数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
输出描述:
左上角到右下角的最短路径。

import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;

/**
 * 迷宫路径-深度优先搜索
 * 
 * @author 过路的守望
 *
 */
public class Labyrinth {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int N = in.nextInt();
            int M = in.nextInt();
            /*
             * 用双端队列打印时无需翻转顺序
             */
            Deque<Node> deque = new LinkedList<>();
            Node[][] data = new Node[N][M];
            /*
             * 四个搜索方向
             */
            int[][] dir = { { 0, 1 }, { 1, 0 }};
            /*
             * 接收数据
             */
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    data[i][j] = new Node(in.nextInt(), i, j);
                }
            }
            /*
             * 添加起点
             */
            deque.offerLast(data[0][0]);
            data[0][0].setVisited(true);
            Node cur = null;
            int i = 0;
            int j = 0;
            /*
             * 是否搜索到符合条件的下一个节点
             */
            boolean find = false;
            while (!deque.isEmpty()) {
                cur = deque.peekLast();
                i = cur.getX();
                j = cur.getY();
                find = false;
                /*
                 * 横竖方向搜索
                 */
                for (int n = 0; n <2; n++) {
                    i = i + dir[n][0];
                    j = j + dir[n][1];
                    if (i >= 0 && i < N && j >= 0 && j < M
                            && !data[i][j].isVisited()) {
                        /*
                         * 搜索到符合条件加入队列退出
                         */
                        if (data[i][j].getValue() == 0) {
                            deque.offerLast(data[i][j]);
                            data[i][j].setVisited(true);
                            find = true;
                            break;
                        } else {
                            /*
                             * i,j下标恢复
                             */
                            i = cur.getX();
                            j = cur.getY();
                        }
                    }
                }
                /*
                 * 搜索已完成,退出循环
                 */
                if (deque.peekLast() == data[N - 1][M - 1]) {
                    break;
                }
                /*
                 * 当前节点无法搜索到符合条件的下一个节点,从队列中删除,标记已访问过
                 */
                if (!find) {
                    cur = deque.pollLast();
                    cur.setVisited(true);
                }
            }
            /*
             * 打印路径
             */
            for (Node node : deque) {
                System.out.println("(" + node.getX() + "," + node.getY() + ")");
            }
        }
        in.close();
    }
}
/*
 * 节点元素类
 */
class Node {
    /*
     * 节点值0或1
     */
    private int value;
    /*
     * x,y节点所在位置下标
     */
    private int x;
    private int y;
    /*
     * 标记是否访问
     */
    private boolean visited = false;

    public Node(int value) {
        super();
        this.value = value;
    }

    public Node(int value, int x, int y) {
        super();
        this.value = value;
        this.x = x;
        this.y = y;
    }

    public int getValue() {
        return value;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public boolean isVisited() {
        return visited;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public void setVisited(boolean visited) {
        this.visited = visited;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

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

/**
 * 迷宫路径 广度优先搜索
 * 
 * @author 过路的守望
 *
 */
public class Labyrinth {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int N = in.nextInt();
            int M = in.nextInt();
            int[][] map = new int[N][M];
            int[][] visited = new int[N][M];
            int[][] dir = { { 0, 1 }, { 1, 0 } };
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < M; j++) {
                    map[i][j] = in.nextInt();
                }
            }
            Queue<Node> queue = new LinkedList<Node>();
            ArrayList<Node> list = new ArrayList<Node>();
            int i = 0, j = 0;
            Node cur = null;
            Node start = new Node(0, 0);
            queue.offer(start);
            visited[0][0] = 1;
            while (!queue.isEmpty()) {
                cur = queue.poll();
                list.add(cur);
                for (int n = 0; n < 2; n++) {
                    i = cur.getX() + dir[n][0];
                    j = cur.getY() + dir[n][1];
                    if (i >= 0 && i < N && j >= 0 && j < M
                            && visited[i][j] == 0 && map[i][j] == 0) {
                        Node next = new Node(i, j);
                        visited[i][j] = 1;
                        /*
                         * 设置前继节点坐标
                         */
                        next.setPreX(cur.getX());
                        next.setPreY(cur.getY());
                        queue.offer(next);
                    }
                }
            }
            /*
             * 目的节点坐标
             */
            int preX = list.get(list.size() - 1).getX();
            int preY = list.get(list.size() - 1).getY();
            /*
             * 记录路径节点索引
             */
            Stack<Integer> stack = new Stack<Integer>();
            while (true) {
                if (preX == 0 && preY == 0) {
                    break;
                }
                for (int k = 0; k < list.size(); k++) {
                    cur = list.get(k);
                    if (cur.getX() == preX && cur.getY() == preY) {
                        /*
                         * 设置前继节点坐标
                         */
                        preX = cur.getPreX();
                        preY = cur.getPreY();
                        stack.push(k);
                        break;
                    }
                }
            }
            stack.push(0);
            while (!stack.isEmpty()) {
                cur = list.get(stack.peek());
                System.out
                        .println("(" + cur.getX() + "," + cur.getY() + ")");
                stack.pop();
            }

        }
        in.close();
    }
}

class Node {
    /*
     * 节点坐标x,y.
     */
    private int x;
    private int y;
    /*
     * 前一个节点坐标
     */
    private int preX;
    private int preY;

    public Node(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }

    public int getPreX() {
        return preX;
    }

    public int getPreY() {
        return preY;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void setPreX(int preX) {
        this.preX = preX;
    }

    public void setPreY(int preY) {
        this.preY = preY;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值