題目描述
小青蛙有一天不小心落入了一個地下迷宮,小青蛙希望用自己僅剩的體力值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;
}
}