题目地址:
https://leetcode.com/problems/snakes-and-ladders/
给定一个 N × N N\times N N×N棋盘 A A A,对每个格子进行编号,从最左下角开始从 1 1 1编号,向右依次 2 , 3 , . . . , N 2,3,...,N 2,3,...,N,走到最右边则向上走一步是 N + 1 N+1 N+1,然后一路再向左依次是 N + 2 , N + 3 , . . . , 2 N N+2,N+3,...,2N N+2,N+3,...,2N,这样走到第 0 0 0行直至走到 N 2 N^2 N2这个位置。从编号 1 1 1的位置出发,每次处于 a a a的时候,可以走到 a + j , j = 1 , 2 , . . . , 6 a+j,j=1,2,...,6 a+j,j=1,2,...,6这些位置(当然这些位置的编号不能超出 N 2 N^2 N2),如果 A A A在这个位置不等于 − 1 -1 −1,那么就需要瞬间移动到 A A A在此处的值对应的编号的位置(瞬移是强制的,不消耗步数)。问从 1 1 1出发至少需要走多少步能走到 N 2 N^2 N2这个位置。题目保证 A [ N − 1 ] [ 0 ] = − 1 A[N-1][0]=-1 A[N−1][0]=−1,并且 N > 1 N>1 N>1。
参考https://blog.csdn.net/qq_46105170/article/details/110944757。代码如下:
import java.util.ArrayDeque;
import java.util.Queue;
public class Solution {
public int snakesAndLadders(int[][] board) {
int n = board.length;
// 一定要注意起点终点重合的情况
if (n == 1) {
return 0;
}
Queue<Integer> queue = new ArrayDeque<>();
queue.offer(0);
boolean[] visited = new boolean[n * n];
visited[0] = true;
int res = 0;
while (!queue.isEmpty()) {
res++;
int size = queue.size();
for (int i = 0; i < size; i++) {
int cur = queue.poll();
for (int j = 1; j <= 6; j++) {
if (cur + j == n * n - 1) {
return res;
}
if (cur + j >= n * n) {
break;
}
int[] nextPos = transform(cur + j, n);
int x = nextPos[0], y = nextPos[1];
// 如果需要瞬移,则强制瞬移
if (board[x][y] != -1) {
if (board[x][y] == n * n) {
return res;
}
if (!visited[board[x][y] - 1]) {
visited[board[x][y] - 1] = true;
queue.offer(board[x][y] - 1);
}
continue;
}
if (!visited[cur + j]) {
visited[cur + j] = true;
queue.offer(cur + j);
}
}
}
}
return -1;
}
private int[] transform(int x, int n) {
return new int[]{n - 1 - x / n, x / n % 2 == 0 ? x % n : n - 1 - x % n};
}
}
时空复杂度 O ( n 2 ) O(n^2) O(n2)。