滴滴出行之地下迷宫

来源:互联网 发布:四旋翼飞控编程 编辑:程序博客网 时间:2024/05/17 06:56

题目描述

小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值P跳出这个地下迷宫。为了让问题简单,假设这是一个n*m的格子迷宫,迷宫每个位置为0或者1,0代表这个位置有障碍物,小青蛙达到不了这个位置;1代表小青蛙可以达到的位置。小青蛙初始在(0,0)位置,地下迷宫的出口在(0,m-1)(保证这两个位置都是1,并且保证一定有起点到终点可达的路径),小青蛙在迷宫中水平移动一个单位距离需要消耗1点体力值,向上爬一个单位距离需要消耗3个单位的体力值,向下移动不消耗体力值,当小青蛙的体力值等于0的时候还没有到达出口,小青蛙将无法逃离迷宫。现在需要你帮助小青蛙计算出能否用仅剩的体力值跳出迷宫(即达到(0,m-1)位置)。

输入描述:

输入包括n+1行:
第一行为三个整数n,m(3 <= m,n <= 10),P(1 <= P <= 100)
接下来的n行:
每行m个0或者1,以空格分隔

输出描述:

如果能逃离迷宫,则输出一行体力消耗最小的路径,输出格式见样例所示;如果不能逃离迷宫,则输出”Can not escape!”。 测试数据保证答案唯一

示例

输入
4 4 10 1 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1
输出
[0,0],[1,0],[1,1],[2,1],[2,2],[2,3],[1,3],[0,3]
从题目上看这是一道DFS的题,递归+回溯就可以解决这个问题了。
穷举所有的路径找到消耗最小的那个路径。
画不多说,看下面的代码:

import java.util.LinkedList;import java.util.Scanner;public class UndergroundMaze {    static int[][] map; // 地图    static int mark[][];    // 标记该点是否走过,其中1为走过,0为没走过    static int n, m;    // 地图大小    static int P;       // 体力值    static int hasenergy = 0;    // 找到路径是剩余的体力值    static LinkedList<String> temp = new LinkedList<>();    // 暂存路径    static LinkedList<String> path;     // 最终的路径    static boolean isFind = false;      // 是否找到    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);    // 获取输入流        // 输入        n = sc.nextInt();        m = sc.nextInt();        P = sc.nextInt();        map = new int[n][m];        mark = new int[n][m];        for (int i = 0; i < n; i++) {            for (int j = 0; j < m; j++) {                map[i][j] = sc.nextInt();            }        }        // DFS找路径        DFS(0, 0, P);        if (isFind) {   // 找到了            for (int i = 0; i < path.size(); i++) {                if (i == path.size() - 1) {                    System.out.print(path.get(i));                    continue;                }                System.out.print(path.get(i) + ",");            }        } else {    // 没找到            System.out.println("Can not escape!");        }    }    public static void DFS (int x, int y , int enery) {        if (x >= 0 && x < n && y >= 0 && y < m && map[x][y] == 1 &&                mark[x][y] == 0 &&enery >= 0) { // 满足坐标合法,能走,之前没走过,有体力值            temp.add("[" + x + "," + y + "]");  // 加入暂存的路径            mark[x][y] = 1;     // 标记该点走过            if (x == 0 && y == m - 1) { // 找到出口                if (enery >= hasenergy) {   // 可能会有多条路径,比较找到体力剩余最多的                    hasenergy = enery;                    path = new LinkedList<>(temp);  // 最终路径                }                // 回溯,遍历所有可能的路径,找到一条使用体力最少的路径。                mark[x][y] = 0;                temp.removeLast();                isFind = true;                return;            } else {                // 递归                DFS(x + 1, y, enery);                DFS(x - 1, y, enery - 3);                DFS(x, y + 1, enery - 1);                DFS(x, y - 1, enery - 1);                // 回溯                mark[x][y] = 0;                temp.removeLast();            }        } else            return;    }}