2019独角兽企业重金招聘Python工程师标准>>>
题目描述
500年前,NowCoder是我国最卓越的剑客。他英俊潇洒,而且机智过人^_^。 突然有一天,NowCoder心爱的公主被魔王困在了一个巨大的迷宫中。NowCoder听说这个消息已经是两天以后了,他知道公主在迷宫中还能坚持T天,他急忙赶到迷宫,开始到处寻找公主的下落。 时间一点一点的过去,NowCoder还是无法找到公主。最后当他找到公主的时候,美丽的公主已经死了。从此NowCoder郁郁寡欢,茶饭不思,一年后追随公主而去了。T_T 500年后的今天,NowCoder托梦给你,希望你帮他判断一下当年他是否有机会在给定的时间内找到公主。 他会为你提供迷宫的地图以及所剩的时间T。请你判断他是否能救出心爱的公主。
1.1 输入描述:
题目包括多组测试数据。
每组测试数据以三个整数N,M,T(00)开头,分别代表迷宫的长和高,以及公主能坚持的天数。
紧接着有M行,N列字符,由”.”,”*”,”P”,”S”组成。其中
“.” 代表能够行走的空地。
“*” 代表墙壁,NowCoder不能从此通过。
“P” 是公主所在的位置。
“S” 是NowCoder的起始位置。
每个时间段里NowCoder只能选择“上、下、左、右”任意一方向走一步。
输入以0 0 0结束。
1.2 输出描述:
如果能在规定时间内救出公主输出“YES”,否则输出“NO”。
1.3 输入例子:
4 4 10
....
....
....
S**P
0 0 0
1.4 输出例子:
YES
2 解题思路
可以使用广度优先遍历。从起始点一圈一圈遍历,最先遍历的位置就是最少用的时间,每一圈消耗一个单位的时间。
图2-1 广度优先遍历
3 算法实现
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
/**
* 解法一
* Declaration: All Rights Reserved !!!
*/
public class Main {
public static void main(String[] args) {
// Scanner scanner = new Scanner(System.in);
Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
while (scanner.hasNext()) {
// 迷宫大小
int col = scanner.nextInt();
int row = scanner.nextInt();
// 剩余时间
int time = scanner.nextInt();
if (row == 0 && col == 0 && time == 0) {
break;
}
// NowCoder的开始位置
int px = 0;
int py = 0;
// 公主的位置
int sx = 0;
int sy = 0;
char[][] maze = new char[row][col];
for (int i = 0; i < row; i++) {
String line = scanner.next();
maze[i] = new char[col];
for (int j = 0; j < col; j++) {
maze[i][j] = line.charAt(j);
if (maze[i][j] == 'P') {
px = i;
py = j;
} else if (maze[i][j] == 'S') {
sx = i;
sy = j;
}
}
}
System.out.println(findPath(maze, px, py, sx, sy, time));
}
scanner.close();
}
/**
* 迷宫找最短的路径,使用广度优先遍历
*
* @param maze 迷宫
* @param px NowCoder的开始位置。横坐标
* @param py NowCoder的开始位置。纵坐标
* @param sx 公主的位置。横坐标
* @param sy 公主的位置。纵坐标
* @param time 剩余时间
* @return YES:在time时间内可以找到公主,NO:在time时间内找不到公主
*/
private static String findPath(char[][] maze, int px, int py, int sx, int sy, int time) {
// 迷宫大小
int row = maze.length;
int col = maze[0].length;
// 记录广度优先处理的,当前要处理的坐标
List curr = new LinkedList<>();
// 记录广度优先处理的,下一圈的坐标
List next = new LinkedList<>();
curr.add(px);
curr.add(py);
// 标记已经访问的位置
maze[px][py] = '*';
while (!curr.isEmpty()) {
px = curr.remove(0);
py = curr.remove(0);
if (px == sx && py == sy) {
return "YES";
}
// System.out.println("(" + px + ", " + py + ")");
// 往上走
if (px - 1 >= 0 && maze[px - 1][py] != '*') {
next.add(px - 1);
next.add(py);
maze[px - 1][py] = '*';
}
// 往右走
if (py + 1 < col && maze[px][py + 1] != '*') {
next.add(px);
next.add(py + 1);
maze[px][py + 1] = '*';
}
// 往下走
if (px + 1 < row && maze[px + 1][py] != '*') {
next.add(px + 1);
next.add(py);
maze[px + 1][py] = '*';
}
// 往左走
if (py - 1 >= 0 && maze[px][py - 1] != '*') {
next.add(px);
next.add(py - 1);
maze[px][py - 1] = '*';
}
// 当前层处理完
if (curr.isEmpty()) {
// 剩下的时间减少
time--;
// 时间用完了还没有找到
if (time < 0) {
return "NO";
}
// 处理下一层
else {
List queue = curr;
curr = next;
next = queue;
}
}
}
return "NO";
}
}