500年前,Jesse是我国最卓越的剑客。他英俊潇洒,而且机智过人^_^。
突然有一天,Jesse心爱的公主被魔王困在了一个巨大的迷宫中。Jesse听说这个消息已经是两天以后了,他知道公主在迷宫中还能坚持T天,他急忙赶到迷宫,开始到处寻找公主的下落。 时间一点一点的过去,Jesse还是无法找到公主。最后当他找到公主的时候,美丽的公主已经死了。从此Jesse郁郁寡欢,茶饭不思,一年后追随公主而去了。T_T 500年后的今天,Jesse托梦给你,希望你帮他判断一下当年他是否有机会在给定的时间内找到公主。
他会为你提供迷宫的地图以及所剩的时间T。请你判断他是否能救出心爱的公主。
题目包括多组测试数据。 每组测试数据以三个整数N,M,T(0<n, m<=20,0<t<=100000)开头,分别代表迷宫的长和高,以及公主能坚持的天数。 紧接着有M行,N列字符,由".","*","P","S"组成。其中 "." 代表能够行走的空地。 "*" 代表墙壁,Jesse不能从此通过。 "P" 是公主所在的位置。 "S" 是Jesse的起始位置。 每个时间段里Jesse只能选择“上、下、左、右”任意一方向走一步。 输入以0 0 0结束。
样例输入
m = 4, n = 4, t = 10
迷宫图如下
....
....
....
S**P
样例输出
0
package search; import java.util.LinkedList; import java.util.Queue; import java.util.Stack; /** * 解题思路:以P为根节点,获取相邻节点作为子节点,以此类推,可以获取到最短路径,到达最短路径的深度即为花费的最短时间 * */ public class RescuePrincess { // 移动方向 int[][] move = { { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } }; //终点,以此为基,遍历前面的节点,还原最短路径 Node lastNode; //通过广度优先遍历,获取最短路径 public int getBFS(char[][] visited, int t, int n, int m) { if (n <= 0 || n > 20 || m <= 0 || m > 20 || t <= 0 || visited.length != m || visited[0].length != n) { return -1; } Node hero=getFirstNode(visited); if(hero==null){ return -1; } Queue<Node> path = new LinkedList<Node>(); path.offer(hero); while (!path.isEmpty()) { Node temp = path.poll(); if ((temp.level + 1) > t) { return -1; } for (int i = 0; i < move.length; i++) { //当当前点坐标在边上时,若move方向为负则排除掉 if ((temp.x == 0 && move[i][1] < 0) || (temp.y == 0 && move[i][0] < 0) || (temp.x == (visited[0].length - 1) && move[i][1] > 0) || (temp.y == (visited.length - 1) && move[i][0] > 0)) { continue; } Node p = new Node(temp.x + move[i][1], temp.y + move[i][0], temp.level + 1); if (visited[p.y][p.x] == '.') { visited[p.y][p.x] = '0'; p.pre = temp; path.offer(p); } else if (visited[p.y][p.x] == 'S') { visited[p.y][p.x] = '0'; p.pre = temp; this.lastNode = p; return 0; } } } return -1; } //获取开始节点P的坐标位置 public Node getFirstNode(char[][] visited){ Node hero=new Node(0,0,0); for (int i = 0; i < visited.length; i++) { for (int j = 0; j < visited[0].length; j++) { if ('P' == visited[i][j]) { hero.x = j; hero.y = i; hero.level = 0; visited[i][j] = '0'; return hero; } } } return null; } //打印最短路径 public void printPath(){ Node temp=this.lastNode; Stack<Node> s=new Stack<Node>(); while(temp!=null){ s.push(temp); temp=temp.pre; } while(!s.isEmpty()){ System.out.println(s.pop().toString()); } } public static void main(String[] args) { int N = 4; int M = 7; int T = 10; char a[][] = { { 'S', '.', '*', '.' }, { '.', '.', '*', '.' }, { '.', '.', '.', '.' }, { '.', '.', '*', '.' }, { '.', '.', '.', '.' }, { '.', '.', '*', '.'}, { '.', '*', '*', 'P' } }; RescuePrincess rp = new RescuePrincess(); int res=rp.getBFS(a, T, N, M); if(res==0) rp.printPath(); else System.out.println("公主拯救失败"); } class Node { //x、y为坐标,level为坐标点所在树的深度 int level, x, y; //指向上一个节点 Node pre; public Node(int x, int y, int level) { this.x = x; this.y = y; this.level = level; } public String toString() { return "(" + this.x + "," + this.y + "," + this.level + ")"; } } }