闯迷宫 java求解

问题描述:
题目地址:http://ac.jobdu.com/problem.php?pid=1335
题目描述:
sun所在学校每年都要举行电脑节,今年电脑节有一个新的趣味比赛项目叫做闯迷宫。
sun的室友在帮电脑节设计迷宫,所以室友就请sun帮忙计算下走出迷宫的最少步数。
知道了最少步数就可以辅助控制比赛难度以及去掉一些没有路径到达终点的map。
比赛规则是:从原点(0,0)开始走到终点(n-1,n-1),只能上下左右4个方向走,只能在给定的矩阵里走。

我对这个题目做了改造,我在代码里面静态的构造了矩阵;如果有解,打印出矩阵,并且在打印的矩阵中给出了路径。
比如,矩阵输入为:
0 0 0 0 1
1 0 0 0 1
1 0 0 1 1
1 0 0 0 0
1 1 1 1 0

矩阵输出为:
0 -0…0…0…1
…..|
1…0…0…0…1
…..|
1…0…0…1…1
…..|
1…0 -0 -0 -0
………………….|
1…1…1…1…0

如果没有结果,打印“cannot be solved!”

算法核心:
1. mMaze是整个矩阵的表示,里面blocking表示该位置是否阻塞;closed表示该位置是否已经处理。closed本质就是构造已经处理的闭集。这个没有使用一个新的集合来表示这个闭集,直接使用mMaze本身表示 。
2. 开放集open,用来存放当前正在处理的节点。是一个queue,先进先出。
3. 算法基本思想就是从原点(0)尝试各个有效的方向(是否没有阻塞,是否已经处理过),让后把合理的节点放入到开放集合中,并且设置为closed。直到找到(BASE-1)的节点为止。
4. 如果open中已经没有 元素 ,但是还没有找到目标节点,说明无解。

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

/**
 * Created by deqiang.wang on 2017/12/29.
 */

public class Solver {
    private final static String TAG="GoMaze";
    private final static int SIZE = 5;
    private final static int BASE = SIZE*SIZE;
    Point[] mMaze=new Point[BASE];  //true: blocking; false: open

    private enum MOVE {
        LEFT(-1),
        RIGHT(1),
        UP(-SIZE),
        DOWN(SIZE),
        NONE(0);
        private int _value;

        MOVE(int value) {
            this._value = value;
        }

        public int getValue() {
            return this._value;
        }
    }
    private class Point{
        int pos;
        boolean blocking;
        boolean closed;
        MOVE move;  //the MOVE to current point
    }
    private void createMaze(){
        int[] maze={
                0,0,0,0,1,
                1,0,0,0,1,
                1,0,0,1,1,
                1,0,0,0,0,
                1,1,1,1,0
        };
        for(int i=0;i<BASE;i++){
            mMaze[i] = new Point();
            mMaze[i].move = MOVE.NONE;
            mMaze[i].pos = i;
            mMaze[i].closed = false;
            mMaze[i].blocking = (maze[i]==1);
        }
    }

    private MOVE[] getValidMove(int pos, Point[] maze){
        MOVE[] moves = new MOVE[4];
        int new_pos;
        int y;

        new_pos = MOVE.UP.getValue()+pos;
        if((0<=new_pos) && (!maze[new_pos].blocking) && (!maze[new_pos].closed))
            moves[0] = MOVE.UP;
        else
            moves[0] = MOVE.NONE;

        new_pos = MOVE.DOWN.getValue()+pos;
        if((BASE>new_pos) && (!maze[new_pos].blocking) && (!maze[new_pos].closed))
            moves[1] = MOVE.DOWN;
        else
            moves[1] = MOVE.NONE;

        new_pos = MOVE.LEFT.getValue()+pos;
        y = pos%SIZE;     //y
        if((0<y) && (!maze[new_pos].blocking) && (!maze[new_pos].closed))
            moves[2] = MOVE.LEFT;
        else
            moves[2] = MOVE.NONE;

        new_pos = MOVE.RIGHT.getValue()+pos;
        y = pos%SIZE;     //y
        if(((SIZE-1)>y) && (!maze[new_pos].blocking) && (!maze[new_pos].closed))
            moves[3] = MOVE.RIGHT;
        else
            moves[3] = MOVE.NONE;

        return moves;
    }

    char getChar(MOVE move){
        if(null==move)
            return ' ';
        switch (move){
            case UP:
                //return '|';
            case DOWN:
                return '|';
            case LEFT:
                //return '<';
            //break;
            case RIGHT:
                return '-';
            //break;
            default:
                return ' ';
            //break;
        }
    }
    private void printAllPaths(Point[]maze){
        Point[] thisMaze = new Point[BASE];
        for(int i=0;i<thisMaze.length;i++){
            thisMaze[i] = new Point();
            thisMaze[i].pos = i;
            thisMaze[i].blocking = maze[i].blocking;
        }
        int index=BASE-1;
        Point point = maze[index];
        while(MOVE.NONE !=point.move){
            thisMaze[index].move = point.move;
            index = index - point.move.getValue();
            point = maze[index];
        }

        for(int i=0;i<SIZE;i++) {
            for(int m=0;m<2;m++) {
                System.out.print("\n"+TAG+" ");
                for (int j = 0; j < SIZE; j++) {
                    if(m==0){
                        if((MOVE.UP==thisMaze[i*SIZE+j].move) || (MOVE.DOWN==thisMaze[i*SIZE+j].move))
                            System.out.print("|  ");
                        else
                            System.out.print("   ");
                    }else{
                        if((MOVE.LEFT==thisMaze[i*SIZE+j].move) || (MOVE.RIGHT==thisMaze[i*SIZE+j].move))
                            System.out.print(String.format("-%d ",thisMaze[i*SIZE+j].blocking?1:0));
                        else
                            System.out.print(String.format(" %d ",thisMaze[i*SIZE+j].blocking?1:0));
                    }
                }
            }
        }

        System.out.println("");
    }
    private boolean solve(Point[] maze){
        Queue<Point> open = new LinkedList<>();

        for(int i=0;i<maze.length;i++){
            maze[i].move = MOVE.NONE;
            maze[i].closed = false;
            maze[i].pos = i;
        }

        if(maze[0].blocking)
            return false;
        else {
            maze[0].closed=true;
            open.offer(maze[0]);
        }

        while(!open.isEmpty()){
            Point node = open.poll();
            //try all directions
            MOVE[] valid_move = getValidMove(node.pos, maze);
            for(int i=0;i<valid_move.length;i++){
                if(valid_move[i]==MOVE.NONE)
                    continue;
                //valid move, mark the node
                int new_pos = node.pos + valid_move[i].getValue();
                maze[new_pos].closed = true;
                maze[new_pos].move = valid_move[i];
                if(new_pos == (BASE-1)){
                    printAllPaths(maze);
                    return true;
                }
                open.offer(maze[new_pos]);
            }
        }
        return false;
    }
    public void start(){
        createMaze();
        printAllPaths(mMaze);
        if(!solve(mMaze))
            System.out.println(TAG+" the maze cannot be solved!");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值