题目说要找最短的路,遇到怪兽还要花时间打怪兽,选用的就是BFS了,根据队列先进先出的特点,达到目标点即是最短的路径。所以在遇到怪兽的时候,我们可以模拟打怪兽,将此点重新入队,这样的操作,当到达顶点的时候,也是最短的路径。而如何得知它的路径呢?我们可以在新节点入队的时候,将上一个节点存起来,那么在终点的时候,就可以回溯找到原来的路径了。下面的代码就是BFS + 队列实现AC。
import java.util.*;
public class Main {
private static class Node {
int x;//x坐标
int y;//y坐标
int step;//当钱步数
Node node;//记录上一个节点到此节点
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextInt()) {
int n = sc.nextInt();//行
int m = sc.nextInt();//列
String temp = sc.nextLine();//读取隐藏的换行符
char[][] map = new char[n][m];//地图
int[][] flag = new int[n][m];//标记
//画地图
for (int i = 0; i < n; i++) {
String data = sc.nextLine();
for (int j = 0; j < m; j++) {
map[i][j] = data.charAt(j);
}
}
//起点
Node start = new Node();
start.x = 0;
start.y = 0;
start.step = 0;
Queue queue = new LinkedList<>();
//把起点入队
queue.offer(start);
while (!queue.isEmpty()) {
//拿队头元素
Node node = queue.peek();
//如果是终点
if (node.x == n - 1 && node.y == m - 1) {
while (map[node.x][node.y] >= '1' && map[node.x][node.y] <= '9') {
Node location = new Node();
location.x = node.x;
location.y = node.y;
location.step = node.step;
location.node = node.node;
node.step++;
node.node = location;
//怪物的hp减一
map[node.x][node.y]--;
}
break;//结束
}//如果不是终点
else {
//出队
node = queue.poll();
//标记走过
flag[node.x][node.y] = 1;
//将周围符合条件的入队
int x = node.x;
int y = node.y;
int step = node.step;
//如果此时的位置有怪物,原地入队
if (!(map[x][y] >= '1' && map[x][y] <= '9')) {
//上)
Node up = null;
if (x - 1 >= 0 && map[x - 1][y] != 'X' && flag[x - 1][y] != 1) {
up = new Node();
up.x = x - 1;
up.y = y;
up.step = step + 1;//当前步数加1
up.node = node;
flag[x-1][y] = 1;
queue.offer(up);
}
//下
Node down = null;
if (x + 1 < n && map[x + 1][y] != 'X' && flag[x + 1][y] != 1) {
down = new Node();
down.x = x + 1;
down.y = y;
down.step = step + 1;
down.node = node;
flag[x+1][y] = 1;
queue.offer(down);
}//左
Node left = null;
if (y - 1 >= 0 && map[x][y - 1] != 'X' && flag[x][y - 1] != 1) {
left = new Node();
left.x = x;
left.y = y - 1;
left.step = step + 1;
left.node = node;
flag[x][y-1] = 1;
queue.offer(left);
}
//右
Node right = null;
if (y + 1 < m && map[x][y + 1] != 'X' && flag[x][y + 1] != 1) {
right = new Node();
right.x = x;
right.y = y + 1;
right.step = step + 1;
right.node = node;
flag[x][y+1] = 1;
queue.offer(right);
}
} else {
{
Node location = new Node();
location.x = x;
location.y = y;
location.step = step + 1;
location.node = node;
//怪物的hp减一
map[x][y]--;
queue.offer(location);
}
}
node = null;
start = null;
}
}
String finish = "FINISH";
if (!queue.isEmpty()) {
StringBuffer sb = new StringBuffer("It takes ");
sb.append(queue.peek().step);
sb.append(" seconds to reach the target position, let me show you the way.");
System.out.println(sb.toString());
pf(queue.peek());
System.out.println(finish);
} else {
System.out.println("God please help our poor hero.");
System.out.println(finish);
}
queue.clear();
queue = null;
}
}
public static void pf(Node node) {
if (node.x == 0 && node.y == 0)
return;
pf(node.node);
StringBuffer s = new StringBuffer();
if (node.x == node.node.x && node.y == node.node.y)
s.append(node.step).append("s:FIGHT AT (").append(node.x).append(",").append(node.y).append(")");
else
s.append(node.step).append("s:(").append(node.node.x).append(",").append(node.node.y).append(")->(")
.append(node.x).append(",").append(node.y).append(")");
System.out.println(s);
}
}
看到别人的博客后,得知优先队列可以实现,也用优先队列实现了一次,下面是AC代码。
import java.util.*;
public class Main {
private static class Node {
int x;//x坐标
int y;//y坐标
int step;//当钱步数
Node node;//记录上一个节点到此节点
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextInt()) {
int n = sc.nextInt();//行
int m = sc.nextInt();//列
String temp = sc.nextLine();//读取隐藏的换行符
char[][] map = new char[n][m];//地图
int[][] flag = new int[n][m];//标记
int[] mx = {0, 0, 1, -1};
int[] my = {1, -1, 0, 0};
//画地图
for (int i = 0; i < n; i++) {
String data = sc.nextLine();
for (int j = 0; j < m; j++) {
map[i][j] = data.charAt(j);
}
}
//起点
Node start = new Node();
start.x = 0;
start.y = 0;
start.step = 0;
Comparator comparator = new Comparator() {
public int compare(Node o1, Node o2) {
return o1.step - o2.step;
}
};
Queue queue = new PriorityQueue<>(comparator);
//把起点入队
queue.offer(start);
Node res = null;
while (!queue.isEmpty()) {
//出队
Node node = queue.poll();
int x = node.x;
int y = node.y;
int step = node.step;
flag[x][y] = 1;
//如果到了终点
if (x == n - 1 && y == m - 1) {
res = node;
break;
}
//bfs
for (int i = 0; i < 4; i++) {
int x1 = x + mx[i];
int y1 = y + my[i];
//判断入队的条件
if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && map[x1][y1] != 'X' && flag[x1][y1] != 1) {
char c = map[x1][y1];
Node tempNode = new Node();
tempNode.x = x1;
tempNode.y = y1;
tempNode.node = node;
flag[x1][y1] = 1;
if (c == '.')
tempNode.step = step + 1;
else
tempNode.step = step + 1 + c - '0';//基本步数再加打怪物的时间
queue.offer(tempNode);
}
}
}
if (res == null) {
System.out.println("God please help our poor hero.");
System.out.println("FINISH");
} else {
System.out.println("It takes "+res.step+" seconds to reach the target position, let me show you the way.");
pf(res);
System.out.println("FINISH");
}
}
}
public static void pf(Node node) {
if (node.x == 0 && node.y == 0)
return;
pf(node.node);
int value = node.step - node.node.step;
StringBuffer s = new StringBuffer();
s.append(node.node.step + 1).append("s:(").append(node.node.x).append(",").append(node.node.y).append(")->(")
.append(node.x).append(",").append(node.y).append(")\r\n");
for (int i = 0; i < value - 1; i++) {
s.append(node.node.step+2+i).append("s:FIGHT AT (").append(node.x).append(",").append(node.y).append(")\r\n");
}
System.out.print(s);
}
}