剑指Offer——回溯算法解迷宫问题(java版)

  以一个M×N的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计程序,对任意设定的迷宫,求出从入口到出口的所有通路。

  下面我们来详细讲一下迷宫问题的回溯算法。

(入口) 0 0 1 0 0 0 1 0

   0 0 1 0 0 0 1 0

   0 0 1 0 1 1 0 1

   0 1 1 1 0 0 1 0

   0 0 0 1 0 0 0 0

   0 1 0 0 0 1 0 1

   0 1 1 1 1 0 0 1

   1 1 0 0 0 1 0 1

   1 1 0 0 0 0 0 0(出口)

  该图是一个迷宫的图。1代表是墙不能走,0是可以走的路线。只能往上下左右走,直到从左上角到右下角出口。

  做法是用一个二维数组来定义迷宫的初始状态,然后从左上角开始,不停的去试探所有可行的路线,碰到1就结束本次路径,然后探索其他的方向,当然我们要标记一下已经走的路线,不能反复的在两个可行的格子之间来回走。直到走到出口为止,算找到了一个正确路径。

  程序如下,具体做法看注释即可。

package cn.edu.ujn.demo;

/**
 * @author SHQ
 *
 * 迷宫问题求解
 *
 * 思路
 *      递归+回溯
 *
 *      按照右-->左-->下-->上的顺序寻路,已走过的路径用5标志
 *
 *
 */
public class MiGong {  

    public static void main(String[] args) {
        int maxRow,maxLine,p;
        Scanner in = new Scanner(System.in);
        Pattern pattern = Pattern.compile("[ ]+");
        String s = in.nextLine();
        String [] str = pattern.split(s);
        // 获取行
        maxRow = Integer.parseInt(str[0]);
        // 获取列
        maxLine = Integer.parseInt(str[1]);
        // 获取能量值
//        p = Integer.parseInt(str[2]);

        int [][] array = new int [maxRow][maxLine];
        for(int i = 0; i < maxRow; i++){
            for(int j = 0; j < maxLine; j++){
                array[i][j] = in.nextInt();
            }
        }

        Long start = System.currentTimeMillis();
        new MiGong().check(0, 0, array, maxRow, maxLine);
        Long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end-start) + "ms");
    }
     /**
     * 制定走的规则
     * @param i
     * @param j
     * @param array
     * @param maxRow
     * @param maxLine
     */
    private void check(int i, int j, int[][] array, int maxRow, int maxLine)    {
        // 递归出口(如果到达右下角出口)
        if (i == maxRow - 1 && j == maxLine - 1) {
            print(array, maxRow, maxLine);
            return;
        }  

        //向右走
        if (canMove(i, j, i, j + 1, array, maxRow, maxLine)) {
            // 已走过的点置标志位5
            array[i][j] = 5;
            // 从下一个点继续寻路
            check(i, j + 1, array, maxRow, maxLine);
            // 均不可行,则恢复现场
            array[i][j] = 0;
        }
        //向左走
        if (canMove(i, j, i, j - 1, array, maxRow, maxLine)) {
            // 标记为已走
            array[i][j] = 5;
            // 递归调用
            check(i, j - 1, array, maxRow, maxLine);
            array[i][j] = 0;
        }
        //向下走
        if (canMove(i, j, i + 1, j, array, maxRow, maxLine)) {
            array[i][j] = 5;
            check(i + 1, j, array, maxRow, maxLine);
            array[i][j] = 0;
        }
        //向上走
        if (canMove(i, j, i - 1, j, array, maxRow, maxLine)) {
            array[i][j] = 5;
            check(i - 1, j, array,maxRow, maxLine);
            array[i][j] = 0;
        }
 }
    /**
     * 判断[i,j]-->[targetI,targetJ]是否可行
     * @param i
     * @param j
     * @param targetI
     * @param targetJ
     * @param array
     * @param maxRow
     * @param maxLine
     * @return boolean 可否通过
     */
    private boolean canMove(int i, int j, int targetI, int targetJ, int[][] array, int maxRow, int maxLine) {
//        System.out.println("从第" + (i + 1) + "行第" + (j + 1) + "列,走到第" + (targetI + 1) + "行第" + (targetJ + 1) + "列");
        if (targetI < 0 || targetJ < 0 || targetI >= maxRow || targetJ >= maxLine) {
//            System.out.println("到达最左边或最右边,失败了");
            return false;
        }
        if (array[targetI][targetJ] == 1) {
//            System.out.println("目标是墙,失败了");
            return false;
        }
        //避免在两个空格间来回走
        if (array[targetI][targetJ] == 5) {
//            System.out.println("来回走,失败了");
            return false;
        }

        return true;
    }
    /**
     * 打印可行路径
     * @param array
     * @param maxRow
     * @param maxLine
     */
    private void print(int [][] array, int maxRow, int maxLine) {
        System.out.println("得到一个解:");
        for (int i = 0; i < maxRow; i++) {
            for (int j = 0; j < maxLine; j++) {
                System.out.print(array[i][j] + " ");
            }
            System.out.println();
        }
    }
} 

  计算结果如下:



美文美图



剑指Offer——回溯算法解迷宫问题(java版)的更多相关文章

  1. 剑指Offer——回溯算法

    剑指Offer--回溯算法 什么是回溯法 回溯法实际是穷举算法,按问题某种变化趋势穷举下去,如某状态的变化用完还没有得到最优解,则返回上一种状态继续穷举.回溯法有"通用的解题法"之 ...

  2. 剑指Offer——分治算法

    剑指Offer--分治算法 基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更 ...

  3. 剑指Offer——动态规划算法

    剑指Offer--动态规划算法 什么是动态规划? 和分治法一样,动态规划(dynamic programming)是通过组合子问题而解决整个问题的解. 分治法是将问题划分成一些独立的子问题,递归地求解 ...

  4. 剑指Offer——贪心算法

    剑指Offer--贪心算法 一.基本概念 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解.虽然贪心算法不能对 ...

  5. 《剑指offer》算法题第十二天

    今天是<剑指offer>算法题系列的最后一天了,但是这个系列并没有包括书上的所有题目,因为正如第一天所说,这些代码是在牛客网上写并且测试的,但是牛客网上并没有涵盖书上所有的题目. 今日题目 ...

  6. 《剑指offer》算法题第一天

    按照个人计划,从今天开始做<剑指offer>上面的算法题,练习平台为牛客网,上面对每道题都有充分的测试实例,感觉还是很不错的.今天下午做了四道题,分别为: 1. 二叉树的深度(书55题) ...

  7. JS数据结构与算法 - 剑指offer二叉树算法题汇总

    ❗❗ 必看经验 在博主刷题期间,基本上是碰到一道二叉树就不会碰到一道就不会,有时候一个下午都在搞一道题,看别人解题思路就算能看懂,自己写就呵呵了.一气之下不刷了,改而先去把二叉树的基础算法给搞搞懂,然 ...

  8. 《剑指offer》算法题第十天

    今日题目: 数组中的逆序对 两个链表的第一个公共节点 数字在排序数组中出现的次数 二叉搜索树的第k大节点 字符流中第一个不重复的字符 1. 数组中的逆序对 题目描述: 在数组中的两个数字,如果前面一个 ...

  9. 《剑指offer》算法题第十一天

    今日题目: 滑动窗口的最大值 扑克牌中的顺子 圆圈中最后剩下的数字 求1+2+3+...+n 不用加减乘除做加法 构建乘积数组 今天的题目比较有意思,可以学到很多知识,包括第1题中的数据结构——双向队 ...

随机推荐

  1. [NOIp 2017]宝藏

    Description 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋 ...

  2. ●BZOJ 2434: [Noi2011]阿狸的打字机

    ●赘述题目 (题意就不赘述了) ●解法: ●我先想的一个比较暴力的方法(要TLE): (ac自动机)先求出last数组(参见刘汝佳的解释:last[j]:表示j节点沿着失配指针往回走时,遇到的下一个单 ...

  3. JAVA 访问WebRoot下的目录文件

    转自 http://blog.csdn.net/jian_csdn/article/details/46119313 ClassLoader classLoader = Thread.currentT ...

  4. dataview findrows

    DataView dvStu = dsStu.Tables[0].Copy().DefaultView;//当前学年学期下所有学生 dvStu.Sort = "bjmc,xm"; ...

  5. Redis数据库之概念与创建服务

      概念                                  Remote   Dictionary  Server key-value  数据库存储系统,数据结构服务器. 键是Stri ...

  6. Linux上rpm实战搭建FTP服务器

    1.检测是否已安装FTP服务 # rpm -qa|grep vsftpd 2.未安装ftp服务的前提进行使用rpm安装 # yum install vsftpd -y Loaded plugins: ...

  7. 47. Permutations II(medium, backtrack, 重要, 条件较难思考)

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  8. [原创]基于VueJs的前后端分离框架搭建之完全攻略

    首先请原谅本文标题取的有点大,但并非为了哗众取宠.本文取这个标题主要有3个原因,这也是写作本文的初衷: (1)目前国内几乎搜索不到全面讲解如何搭建前后端分离框架的文章,讲前后端分离框架思想的就更少了, ...

  9. Emacs Python 自动补全--Elpy

    安装方法: 首先,安装一些依赖包: # Either of these pip install rope pip install jedi # flake8 用来检查语法错误 pip install ...

  10. centos 6安装opencv

    昨天装好的,今天有些细节已经记不起来里,大致写一下吧. 首先,从opencv官网下载linux的opencv-2.4.9安装包,下载地址:http://jaist.dl.sourceforge.net ...