DFS BFS回顾

Posted by 水的一匹Lu的Blog on Wednesday, August 7, 2019

TOC

DFS BFS回顾

前言:这次回顾用一道简单的BFS,DFS入门题目进行。其实一年之前就学习过DFS,BFS,并且用C++ AC了这一道题目,当时初学时的自己在AC过后,兴奋之余也没想着要经常温习回顾,这也是导致今天再次做到这道题时,磕磕绊绊,思前想后,敲代码时犹豫不决的原因之一;这也鞭策我要经常温习之前学过的知识。


话不多说,先上题:(题目来自HNUCM)

题目描述

小明置身于一个迷宫,请你帮小明找出从起点到终点的最短路程。 小明只能向上下左右四个方向移动

输入

输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。 每组输入的第一行是两个整数N和M(1<=N,M<=100)。 接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。 字符的含义如下: ‘S’:起点 ‘E’:终点 ‘-’:空地,可以通过 ‘#’:障碍,无法通过 输入数据保证有且仅有一个起点和终点。

输出

对于每组输入,输出从起点到终点的最短路程,如果不存在从起点到终点的路,则输出-1。

样例输入

1
5 5
S-###
-----
##---
E#---
---##

样例输出

9

这次我用Java对这道题进行回顾

首先上DFS(一条路走到黑),这种用时间换取空间的做法大多会TLE,事实也确实如此,这道题可以用DFS解出来,但是会超时,因为反复的递归耗费了大量的时间。

DFS code:

import java.util.Queue;
import java.util.Scanner;

public class HNUCM_1221_DFS {
    public static int p,q;

    //存放地图的数组
    public static char[][] arr;

    //标记数组
    public static int[][] maker;

    public static int sx,sy,gx,gy;

    //初始化最短值
    public static int min = 99999;

    public static int[] dx = {1,0,-1,0};
    public static int[] dy = {0,1,0,-1};

    public static void dfs(int x,int y,int step){
        //到达终点
        if (x==gx && y==gy){
            if (step < min){
                min = step;
            }
            return;
        }
        //向四个方向走
        for (int i = 0; i < 4 ;i++){
            int nx = x+dx[i];
            int ny = y+dy[i];
            //判断有没有出界,如果出界退出此次循环
            if (nx > p-1 || nx < 0 || ny > q-1 || ny < 0){
                continue;
            }

            //判断有没有碰壁
            if (arr[nx][ny] != '#' && maker[nx][ny] == 0){
//                System.out.println(nx+" "+ny);
                //标记走过
                maker[nx][ny] = 1;
                dfs(nx,ny,step+1);
                //取消标记
                maker[nx][ny] = 0;
            }
        }
        return;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);


        int n = sc.nextInt();

        while (n-->0){
            p = sc.nextInt();
            q = sc.nextInt();

            arr = new char[p][q];
            maker = new int[p][q];
            //初始化迷宫
            for (int i = 0 ;i < p ;i++){
                String b = sc.next();
                for (int j = 0 ; j < q ;j++){
                    arr[i][j] = b.charAt(j);
                    //确定起点,终点坐标
                    if (arr[i][j] == 'S'){
                        sx = i;
                        sy = j;
                    }
                    if (arr[i][j] == 'E'){
                        gx = i;
                        gy = j;
                    }
                }
            }

            dfs(sx,sy,0);

//            System.out.println(sx+" "+sy);
            if (min == 99999){
                min = -1;
            }

            System.out.println(min);
            min = 99999;
        }
    }
}

BFS code:

import java.util.LinkedList;
import java.util.Scanner;

public class HNUCM_1221_BFS {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int min = 99999;

        //方向数组
        int[] dx = {1,0,-1,0};
        int[] dy = {0,1,0,-1};

        //输入数据组数
        int n = sc.nextInt();


        while (n-- > 0) {
            int p = sc.nextInt();
            int q = sc.nextInt();

            char[][] map = new char[p][q];
            int sx = 0,sy = 0,gx = 0,gy = 0;
            //初始化地图
            for (int i = 0 ; i < p ;++i){
                String a = sc.next();
                for (int j = 0 ;j < q ; ++j){
                    map[i][j] = a.charAt(j);
                    if (map[i][j] == 'S') {
                        sx = i;
                        sy = j;
                    }
                    if (map[i][j] == 'E') {
                        gx = i;
                        gy = j;
                    }
                }
            }
            Node start = new Node(sx,sy,null);
            //创建队列,BFS准备工作
            LinkedList<Node> queue = new LinkedList<>();
            //创建临时节点
            Node tmp = null;
            //压入开始节点
            queue.offer(start);
            //开始bfs搜素地图
            ok:
            while (!queue.isEmpty()) {
                //出队第一个节点
                tmp = queue.poll();
                //遍历四个方向
                for (int i = 0 ; i < 4;++i){
                    int nx = tmp.x + dx[i];
                    int ny = tmp.y + dy[i];
                    //看是否超出边界
                    if (nx < 0 || nx > p-1 || ny < 0 || ny > q-1) {
                        continue;
                    }
                    if (map[nx][ny] == '#') {
                        continue;
                    }
                    Node next = new Node(nx,ny,tmp);
                    //找到终点
                    if (nx == gx && ny == gy) {
//                        min = next.dis-1;
                        queue.clear();
                        queue.offerFirst(next);
                        Node preNode = next.pre;
                        while (preNode != null) {
                            queue.offerFirst(preNode);
                            preNode = preNode.pre;
                        }
                        min = queue.size();
                        System.out.println(min-1);
                        break ok;
                    }
                    map[nx][ny] = '#';
                    queue.offer(next);
                }
            }
            if (min == 99999){
                System.out.println(-1);
            }
            //这是个坑!!!我第一次把他写在了外面,以至于一直报WA50%
            min = 99999;

        }
    }

}
class Node{
    int x;
    int y;
    int dis;
    Node pre;
    public Node(int x,int y,Node N){
        this.x = x;
        this.y = y;
        this.pre = N;
    }

}

「真诚赞赏,手留余香」

水的一匹Lu的Blog

真诚赞赏,手留余香

使用微信扫描二维码完成支付