问题描述:
题目地址: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!");
}
}