F. Turtle Mission: Robot and the Earthquake -- 题解:
题目大意:
思路解析:
这里再大概描述一下题目, 就是现在有一个机器人需要从(0,0)点前往(n-1,m-1)点去救援,但是因为他前往的路上有岩石,如果他碰上了岩石他就会被击毁,由因为发生了地震,岩石就会沿着列向上进行循环移动。机器人只能向上或者向右或者向下,问最少需要多少步,才能到达终点,如果无解输出-1.
那么我们首先可以想到,只有机器人,岩石在动,如果我们以终点所在地为坐标轴,(以最坏情况 n == 10^3, m == 10^3来考虑这样的时间复杂度), 假如我们机器人当前在点 (i,j),因为周围的岩石在移动,那么他在 (i,j)这个点可能有 10^3的情况,即实际第i行可能表示第 0行岩石情况,可能表示第1行岩石情况....,那么对于10^6的点则共有 10^9的情况,如果使用这样的方法跑一边bfs(或者最短路)一定会超时。
但是假如我们继续考虑上诉情况怎么优化,我们可以发现我们实际需要知道的是我们到达第 (i,j)点当前走路方案下,周围的岩石情况是怎么样的,那我们假如,把坐标系改为岩石,让机器人和终点动,那么对于 (i,j)这个点它便只有一种可能性存在了,那么这样跑bfs(或者最短路)最好情况下时间复杂度也为 10^6是可以接受的。
在岩石坐标系下,我们再来考虑机器人怎么转移:
向上:(在岩石坐标系下,相当于没动,所以这个向上走对于这个坐标系其实是无效的)
向下:(在岩石坐标系下,相当于向下移动两格)
向右: (在固定岩石坐标下,机器人相当于往右下移动)
import java.io.*;
import java.util.*;
public class Main {
static long mod = 998244353;
static int n;
public static void main(String[] args) throws IOException {
FastScanner f = new FastScanner();
PrintWriter w = new PrintWriter(System.out);
int t = f.nextInt();
for (int o = 0; o < t; o++) {
n = f.nextInt();
int m = f.nextInt();
int[][] map = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = f.nextInt();
}
}
boolean[][] vis = new boolean[n][m];
PriorityQueue<Node> nodes = new PriorityQueue<>(new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
if(o1.va != o2.va) return o1.va - o2.va;
else return o2.y - o1.y;
}
});
int ans = Integer.MAX_VALUE;
nodes.add(new Node(0,0,0));
while (!nodes.isEmpty()){
Node cur = nodes.poll();
if(cur.y == m - 1){
ans = Math.min(ans, cur.va + Math.min(Math.abs((n - 1 + cur.va) % n - cur.x), n - Math.abs((n-1 + cur.va) % n - cur.x)));
continue;
}
if (map[(cur.x + 2) % n][cur.y] == 0 && map[(cur.x + 1) % n][cur.y] == 0){
if (!vis[(cur.x + 2) % n][cur.y]){
nodes.add(new Node((cur.x + 2) % n, cur.y, cur.va+1));
vis[(cur.x + 2) % n][cur.y] = true;
}
}
if (cur.y + 1 < m && map[(cur.x + 1) % n][cur.y + 1] == 0){
if (!vis[(cur.x + 1) % n][cur.y + 1]){
nodes.add(new Node((cur.x + 1) % n, cur.y + 1, cur.va+1));
vis[(cur.x + 1) % n][cur.y + 1] = true;
}
}
}
if (ans == Integer.MAX_VALUE) ans = -1;
w.println(ans);
}
w.flush();
w.close();
}
public static class Node{
int x;
int y;
int va;
public Node(int x, int y, int va){
this.x = x;
this.y = y;
this.va = va;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node pair = (Node) o;
return x == pair.x && y == pair.y && (va % n) == (pair.va % n);
}
@Override
public int hashCode() {
return Objects.hash(x, y, 0);
}
}
private static class FastScanner {
final private int BUFFER_SIZE = 1 << 16;
private DataInputStream din;
private byte[] buffer;
private int bufferPointer, bytesRead;
private FastScanner() throws IOException {
din = new DataInputStream(System.in);
buffer = new byte[BUFFER_SIZE];
bufferPointer = bytesRead = 0;
}
private short nextShort() throws IOException {
short ret = 0;
byte c = read();
while (c <= ' ') c = read();
boolean neg = (c == '-');
if (neg) c = read();
do ret = (short) (ret * 10 + c - '0');
while ((c = read()) >= '0' && c <= '9');
if (neg) return (short) -ret;
return ret;
}
private int nextInt() throws IOException {
int ret = 0;
byte c = read();
while (c <= ' ') c = read();
boolean neg = (c == '-');
if (neg) c = read();
do ret = ret * 10 + c - '0';
while ((c = read()) >= '0' && c <= '9');
if (neg) return -ret;
return ret;
}
public long nextLong() throws IOException {
long ret = 0;
byte c = read();
while (c <= ' ') c = read();
boolean neg = (c == '-');
if (neg) c = read();
do ret = ret * 10 + c - '0';
while ((c = read()) >= '0' && c <= '9');
if (neg) return -ret;
return ret;
}
private char nextChar() throws IOException {
byte c = read();
while (c <= ' ') c = read();
return (char) c;
}
private String nextString() throws IOException {
StringBuilder ret = new StringBuilder();
byte c = read();
while (c <= ' ') c = read();
do {
ret.append((char) c);
} while ((c = read()) > ' ');
return ret.toString();
}
private void fillBuffer() throws IOException {
bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
if (bytesRead == -1) buffer[0] = -1;
}
private byte read() throws IOException {
if (bufferPointer == bytesRead) fillBuffer();
return buffer[bufferPointer++];
}
}
}
代码实现: