Java算法---华为oj迷宫问题求解(广度优先搜索)

  一万年太久,只争朝夕,只有坚持,才能胜利,经过昨天的努力,解决了广度优先算法实现迷宫问题,题目在这里不赘述,如果不知道题目的请看我的上一篇博客Java算法—华为oj迷宫问题求解,这里面说的很详细,下来就直奔主题,说说广度优先搜索。

  一般谈起广搜,我的第一反应就是求最短路径,因为广搜是由内向外逐层扩散,最后肯定能找到一个最短的路径,其实用法也不难,我的这篇博客中也讲到了广搜,可以看下Java算法—求面积,今天说的广搜和之前的不同之处在于,之前求最短路径,最终只需给出一个数字表示最短的长度,而不需要输出具体的路径是什么,也就是怎么走,而今天的广搜是需要输出路径,要是谈起这个路径问题,我想大部分人可能觉得深搜比较好,的确,我也是这样觉得,但是我们要灵活运行多种方法去解决一个问题,下来说说具体的题目吧。

  广搜的套路就是利用一个队列,每次将当前点的邻居节点加入队列,然后出队,在将当前点加入队列,一直讲所有路径搜索完毕,直到队列为空停止。同时还需要一个数组去保存该节点是否访问,做个标记。但是怎样输出路径呢,我采取的办法是每次我们需要保存一下当前节点的前驱节点,可以这样设计一个类保存当前坐标和前驱坐标:

<span style="font-family:SimSun;font-size:18px;"><span style="font-size:18px;">class Node{
    int x;
    int y;
    int prex;
    int prey;
}</span></span>

  这样最终我们可以通过前驱节点来输出整个的路径。具体怎样做请往下看,就拿迷宫问题给的样例来说吧,每次将所有出队的节点保存在一个arrayList中,最终arrayList中保存了所有出队的节点,我们怎样从这些节点确定一条路径呢?
输入  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

arrayList中会保存13个节点,分别是

(0,0,0,0)

(1,0,0,0)

(2,0,1,0)

(3,0,2,0)

(2,1,2,0)

(4,0,3,0)

(2,2,2,1)

(4,1,4,0)

(2,3,2,2)

(4,2,4,1)

(2,4,2,3)

(3,4,2,4)

(4,4,3,4)

前两个坐标代表当前坐标位置,后两个代表前驱坐标位置,然后按照从目的节点往起始节点找路径,如下图:

《Java算法---华为oj迷宫问题求解(广度优先搜索)》

这样最终找到了一条路径(0,0)(1,0)(2,0)(2,1)(2,2)(2,3)(2,4)(3,4)(4,4),即是我们最终要求解的问题。这样广度搜索也实现了路径的问题,下来就是写代码了,具体怎么实现每个人都不一样,下面贴上我自己的代码:

<span style="font-family:SimSun;">import java.util.*;

/**
 * Created by Administrator on 2015/12/21.
 */
public class BFS {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        while (sc.hasNext()){
            int m=sc.nextInt();
            int n=sc.nextInt();
            int[][] map = new int[m][n];
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    map[i][j] = sc.nextInt();
                }
            }
            int[][] dir = {{1, 0}, {0, 1}};
            int[][] visited=new int[m][n];
            Node start=new Node(0,0);
            Node end=new Node(m-1,n-1);
            Queue<Node> queue=new LinkedList<Node>();
            ArrayList<Node> arrayList=new ArrayList<Node>();//用来保存每一个出队列的节点
            queue.offer(start);
            while (!queue.isEmpty()){
                Node local=queue.remove();
                arrayList.add(local);
                for (int i=0;i<2;i++){
                    Node nbr=new Node(local.x+dir[i][0],local.y+dir[i][1]);
                    if(nbr.x>=0&&nbr.x<m&&nbr.y>=0&&nbr.y<n&&map[nbr.x][nbr.y]==0&&visited[nbr.x][nbr.y]==0){
                        visited[nbr.x][nbr.y]=1;
                        queue.offer(nbr);
                        nbr.prex=local.x;//保存前驱节点
                        nbr.prey=local.y;//保存前驱节点
                    }
                }
            }
            Stack<Integer> stack=new Stack<Integer>();
            int  px=arrayList.get(arrayList.size()-1).prex;//获得目的节点的前驱节点
            int  py=arrayList.get(arrayList.size()-1).prey;
            stack.push(arrayList.size()-1);//将目的节点在arrayList中的位置记录下来,便于输出
            while (true){
                if(px==0&&py==0){//找到起始节点就停止
                    break;
                }
                for(int i=0;i<arrayList.size();i++){//循环找出每一个节点的前驱,找到就跳出当前循环
                    if(arrayList.get(i).x==px&&arrayList.get(i).y==py){
                        px=arrayList.get(i).prex;
                        py=arrayList.get(i).prey;
                        stack.push(i);//保存节点在arrayList中的位置
                        break;
                    }
                }
            }
            System.out.println("(0,0)");
            while (!stack.isEmpty()){
                System.out.println("("+arrayList.get(stack.peek()).x+","+arrayList.get(stack.peek()).y+")");
                stack.pop();
            }

        }
    }
}

class Node{
    int x;
    int y;
    int prex;//保存前驱节点位置
    int prey;
    Node(int x,int y){
        this.x=x;
        this.y=y;
    }
}</span>

      如果有什么问题,欢迎评论。

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/csdn_yaobo/article/details/50378842
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞