BFS实现简单迷宫问题 JAVA实现

面试题中经常会遇到,给定一个0,1矩阵,0表示可走,1表示不可走。求出从左上角到右下角的最短路径?

例如:矩阵A={
           {0,0,1,0},
           {1,0,1,0},
           {0,0,1,0},
           {0,0,0,0}
   };

这里我们就可以用广度优先算法来实现:

import java.util.LinkedList;
public class MiGong {
	public static void main(String[] args) {
		 int[][] array={
		            {0,0,1,0},
		            {1,0,1,0},
		            {0,0,1,0},
		            {0,0,0,0}
		           };
		 new MiGong().findMinRold(array);
	}
	//定义图的节点信息
	class Node{
		//定义坐标和距离第一个节点的距离
		int x;
		int y;
		int dis;
		//定义节点的前缀,用于绘制整个最短路径的  线路图
		Node pre;
		public Node(int x , int y , int dis , Node pre) {
			this.x = x;
			this.y = y;
			this.dis = dis;
			this.pre = pre;
		}
	}
	
	public void findMinRold(int[][] arr) {
		//定义  上下左右四个方向
		int[][] direction = {{1,0},{-1,0},{0,1},{0,-1}};
		//创建队列
		LinkedList<Node> queue = new LinkedList<Node>();
		//创建开始节点
		Node start = new Node(0,0,0,null);
		//把开始节点放入队列中,并做下标记,在原来数组中做标记
		queue.offer(start);
		arr[0][0] = 1;
		//循环操作队列,进行广度遍历
		Node temp = null;
		ok:
		while(!queue.isEmpty()) {
			temp = queue.poll();
			//依次遍历这个节点的四个方向,查找还没有遍历的相连节点
			for(int i = 0 ; i < 4 ; i++) {
				int newX = temp.x + direction[i][0];
				int newY = temp.y + direction[i][1];
				//是否越界,坐标
				if(newX < 0 || newX >= 4 || newY < 0 || newY >= 4) {
					continue;
				}
				//判断是否该节点可以通过,即为0
				if(arr[newX][newY] == 1) {
					continue;
				}
				//构造节点
				Node next = new Node(newX , newY , temp.dis+1 , temp);
				//该节点可以通过,判断该节点是否是最终节点
				if(newX == 3 && newY == 3) {
					queue.clear();
					//相当于头插法,转置
					queue.offerFirst(next);
					Node preNode = next.pre;
					while(preNode != null) {
						queue.offerFirst(preNode);
						preNode = preNode.pre;
					}
					int len = queue.size();
					System.out.println("最短路径长度为:"+(len-1));
					for(Node it:queue) {
						System.out.println("("+it.x+","+it.y+") ");
					}
					break ok;
				}
				arr[newX][newY] = 1;
				queue.offer(next);
			}//for
			
		}//while
		
	}

}

附录:BFS求解第一个节点到其他节点之间的最短路径问题:

import java.util.LinkedList;
import java.util.Map;
import java.util.TreeMap;

public class BFS {
	public static void main(String[] args) {
		int[][] arr = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
		int[][] mark = new int[4][4];
		new BFS().BFS(arr, mark);
	}
	
	//构造节点,包括x和y、以及与第一个节点的距离
	class Node{
		int x;
		int y;
		int dis;
		public Node(int x , int y , int dis) {
			this.x = x ;
			this.y = y ; 
			this.dis = dis ;
		}
	}
	// 1:使用队列LinkedList  2:使用标记数组mark和坐标
	public void BFS(int[][] arr , int[][] mark) {
		//记录每个节点到第一个节点的最短距离
		Map<Integer,Integer> map = new TreeMap<Integer,Integer>();
		//上下左右四个方向
		int[][] derect = {{1,0},{-1,0},{0,1},{0,-1}};
		//建立一个队列
		LinkedList<Node> queue = new LinkedList<Node>();
		//初始化第一个节点
		Node start = new Node(0,0,0);
		//把第一个节点放到队列中去
		queue.offer(start);
		//置该点标记为为1,表示已经访问过
		mark[0][0] = 1;
		//第一个节点到自己的距离
		map.put(1, 0);
		while(!queue.isEmpty()) {
			//出队列
			Node temp = queue.poll();
			//将其相关联的节点找出来,并依次进入队列
			for(int i = 0 ; i < 4 ; i++) {
				//寻找相连节点
				int newX = temp.x + derect[i][0];
				int newY = temp.y + derect[i][1];
				//新的坐标越界了,继续下一次循环
				if(newX < 0 || newY < 0 || newX >= 4 || newY >= 4) {
					continue;
				}
				//该节点的标记mark为1,已经访问过了,则不需要进队列了
				if(mark[newX][newY] == 1) {
					continue;
				}
				//已经找到相连节点,构建该节点,并入队列,标记为1
				Node next = new Node(newX , newY , temp.dis+1);
				//记录第1个节点到next节点的距离
				map.put(arr[newX][newY], temp.dis+1);
				mark[newX][newY] = 1;
				queue.offer(next);

			}//for
		}//while
		
		//输出节点到1节点的距离
		for(Map.Entry<Integer, Integer> it:map.entrySet()) {
			System.out.println("1->"+it.getKey()+":"+it.getValue());
		}
	}

}

猜你喜欢

转载自blog.csdn.net/qq_37065641/article/details/80341234