迷宫问题:
给定一个大小为N×M的迷宫。迷宫由通道和墙壁组成,每一步可以向邻接的上下左右四格
的通道移动。请求出从起点到终点所需的最小步数。请注意,本题假定从起点一定可以移动
到终点。
输入
N=10, M=10(迷宫如下图所示。'#','.','S','G'分别表示墙壁、通道、起点和终点)
#S######.#
......#..#
.#.##.##.#
.#........
##.##.####
....#....#
.#######.#
....#.....
.####.###.
....#...G#
输出
22
为了方便,将迷宫初始化写在代码里,主要实现在代码注释中
/**
* create by liuxu
* date 2019年3月29日
*/
package arithmetic.migong;
import static org.hamcrest.CoreMatchers.theInstance;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import org.springframework.context.support.StaticApplicationContext;
import com.alibaba.fastjson.serializer.DateFormatSerializer;
/**
* 迷宫问题
* @Description
* @author liuxu
* @date 2019年3月29日
* @version
*/
public class MiGong {
// 迷宫如下图所示。'#','.','S','G'分别表示墙壁、通道、起点和终点)
// 声明一个二维数组,存放迷宫
static String[][] migong = {
{ "#", "S", "#", "#", "#", "#", "#", "#", ".", "#" },
{ ".", ".", ".", ".", ".", ".", "#", ".", ".", "#" },
{ ".", "#", ".", "#", "#", ".", "#", "#", ".", "#" },
{ ".", "#", ".", ".", ".", ".", ".", ".", ".", "." },
{ "#", "#", ".", "#", "#", ".", "#", "#", "#", "#" },
{ ".", ".", ".", ".", "#", ".", ".", ".", ".", "#" },
{ ".", "#", "#", "#", "#", "#", "#", "#", ".", "#" },
{ ".", ".", ".", ".", "#", ".", ".", ".", ".", "." },
{ ".", "#", "#", "#", "#", ".", "#", "#", "#", "." },
{ ".", ".", ".", ".", "#", ".", ".", ".", "G", "#" } };
public static void main(String[] args) {
BFS();
}
/*
* 广度优先搜索
* 广度优先搜索时,如果起始坐标与终点坐标能联调,则此路径必为最短路径
*/
public static void BFS() {
//初始化迷宫起始坐标
Point point = new MiGong().new Point(0, 1);
//初始化迷宫队列
MiGong.MiGongQueue miGongQueue = new MiGong().new MiGongQueue();
miGongQueue.add(point);
//记录一共走了多少步
int count = 0;
//队列中节点x坐标
int queuePointX;
//队列中节点y坐标
int queuePointY;
//队列节点
Point queuePoint;
// 定义一个数组,保存节点是否被访问 0:未被访问,!0:已访问
//其值为起始坐标到达该坐标的步数,初始化为0
int[][] pointVisited = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
//循环队列
while (!miGongQueue.isEmpty()) {
// 队列中的节点信息
queuePoint = miGongQueue.poll();
queuePointX = queuePoint.getPointX();
queuePointY = queuePoint.getPointY();
//当前节点是否为终点
if (migong[queuePointX][queuePointY] == "G") {
System.out.println("{" + queuePointX + "," + queuePointY + "}=>" + migong[queuePointX][queuePointY]
+ "=>" + pointVisited[queuePointX][queuePointY]);
break;
}
//System.out.println("{" + queuePointX + "," + queuePointY + "}=>" + migong[queuePointX][queuePointY]+ "=>" + pointVisited[queuePointX][queuePointY]);
/**
* //i,j 起始坐标 //i-1,j 起始坐标-左 //i+1,j 起始坐标-右 //i,j-1 起始坐标-上 //i,j+1 起始坐标-下
*/
//可以使用for循环
//向左走
if (queuePointX - 1 > 0 && pointVisited[queuePointX - 1][queuePointY] == 0) {
if (migong[queuePointX - 1][queuePointY] != "#") {
//可以走通,节点加入队列
miGongQueue.add(new MiGong().new Point(queuePointX - 1, queuePointY));
//到达此坐标所需要的步数
pointVisited[queuePointX - 1][queuePointY] = pointVisited[queuePointX][queuePointY] + 1;
}
}
//右走
if (queuePointX + 1 < 10 && pointVisited[queuePointX + 1][queuePointY] == 0) {
if (migong[queuePointX + 1][queuePointY] != "#") {
miGongQueue.add(new MiGong().new Point(queuePointX + 1, queuePointY));
pointVisited[queuePointX + 1][queuePointY] = pointVisited[queuePointX][queuePointY] + 1;
}
}
//上走
if (queuePointY - 1 > 0 && pointVisited[queuePointX][queuePointY - 1] == 0) {
if (migong[queuePointX][queuePointY - 1] != "#") {
miGongQueue.add(new MiGong().new Point(queuePointX, queuePointY - 1));
pointVisited[queuePointX][queuePointY - 1] = pointVisited[queuePointX][queuePointY] + 1;
}
}
//下走
if (queuePointY + 1 < 10 && pointVisited[queuePointX][queuePointY + 1] == 0) {
if (migong[queuePointX][queuePointY + 1] != "#") {
miGongQueue.add(new MiGong().new Point(queuePointX, queuePointY + 1));
pointVisited[queuePointX][queuePointY + 1] = pointVisited[queuePointX][queuePointY] + 1;
}
}
}
}
/*
* 迷宫队列-广度优先搜索
*/
class MiGongQueue {
/**
*
*/
public MiGongQueue() {
// TODO Auto-generated constructor stub
}
Queue<Point> queue = new LinkedBlockingQueue<MiGong.Point>();
public void add(Point point) {
this.queue.add(point);
}
public boolean isEmpty() {
return queue.isEmpty();
}
public Point poll() {
return this.queue.poll();
}
}
/*
* 坐标类
*/
class Point {
int pointX;
/**
* @return the pointX
*/
public int getPointX() {
return pointX;
}
/**
* @param pointX
* the pointX to set
*/
public void setPointX(int pointX) {
this.pointX = pointX;
}
/**
* @return the pointY
*/
public int getPointY() {
return pointY;
}
/**
* @param pointY
* the pointY to set
*/
public void setPointY(int pointY) {
this.pointY = pointY;
}
int pointY;
/**
*
*/
public Point(int x, int y) {
this.pointX = x;
this.pointY = y;
}
}
}