试题 A: 星期计算
[题解]
方法一:费马小定理
费马小定理:若 m 是一个质数, 整数 a 不是 m 的倍数,则 a m − 1 ≡ 1 ( m o d m ) a^{m - 1} \equiv 1 (mod \, m) am−1≡1(modm) 成立
代入可得 2 0 6 ≡ 1 ( m o d 7 ) 20^6 \equiv 1 (mod \, 7) 206≡1(mod7) 可推出 2 0 22 ≡ 2 0 4 ( m o d 7 ) 20^{22} \equiv 20^4 (mod \, 7) 2022≡204(mod7),即 160000 mod 7 = 1,则答案为 星期六往后数一天——星期天
方法二:代码求解
恰好整除,则证明为星期天
public class Main {
public static void main(String[] args) {
int ans = 1;
for (int i = 0; i < 22; i++) {
ans = (ans * 20) % 7;
}
ans = (ans + 6) % 7;
System.out.println(ans);
}
}
[答案]
7
试题 B: 山
[题解]
public class Main {
public static void main(String[] args) {
int ans = 0;
for (int i = 2022; i <= 2022222022; i++) {
String s = i + "";
int left = 0, right = s.length() - 1;
if (s.charAt(left) != s.charAt(right)) continue;
left++;
right--;
while (left <= right) {
if (s.charAt(left) < s.charAt(left - 1)) break;
if (s.charAt(left) != s.charAt(right)) break;
left++;
right--;
}
if (left > right) ans++;
}
System.out.println(ans);
}
}
[答案]
3138
试题 C: 字符统计
[题解]
import java.io.*;
/**
* 2022 字符统计 哈希
*
*/
public class Main {
static BufferedReader br;
static StreamTokenizer st;
static PrintWriter pr;
public static void main(String[] args) throws Exception{
br = new BufferedReader(new InputStreamReader(System.in));
st = new StreamTokenizer(br);
pr = new PrintWriter(new OutputStreamWriter(System.out));
String str = br.readLine();
char[] s = str.toCharArray();
int[] cnt = new int[26];
for(int i = 0; i < 26; i++) {
cnt[i] = 0;
}
for(char c : s) {
cnt[c - 'A']++;
}
String ans = "A";
int max = cnt[0];
for(int i = 1; i < 26; i++) {
if (max < cnt[i]) {
max = cnt[i];
ans = "" + (char)('A' + i);
} else if(max == cnt[i]) {
ans += (char)('A' + i);
}
}
pr.println(ans);
pr.flush();
}
}
试题 D: 最少刷题数
[题解]
import java.io.*;
import java.util.*;
/**
* 2022 最少刷题数 模拟
*
*/
public class Main {
static BufferedReader br;
static StringTokenizer st;
static PrintWriter pw;
public static void main(String[] args) throws IOException {
br = new BufferedReader(new InputStreamReader(System.in));
st = new StringTokenizer(br.readLine());
pw = new PrintWriter(new OutputStreamWriter(System.out));
new Main().go();
pw.flush();
}
void go() throws IOException {
int n = Integer.parseInt(st.nextToken());
String str = br.readLine();
String strArr[] = str.split(" ");
//将 n 为 1 特判出去,表示接下来数至少有两个
if (n == 1) {
pw.print("0 ");
return;
}
List<Integer> nums = new ArrayList<>();
List<Integer> numsCopyed = new ArrayList<>();
for (String s : strArr) {
int i = Integer.parseInt(s);
nums.add(i);
numsCopyed.add(i);
}
Collections.sort(numsCopyed);
int mid = numsCopyed.get(n / 2);
boolean lRepeat = mid == numsCopyed.get(n / 2 - 1);
boolean isOdd = (n & 1) == 1;
boolean lRepeatTwo = false;
if (!isOdd && n >= 4) {
lRepeatTwo = mid == numsCopyed.get(n / 2 - 2);
}
boolean rRepeat = false;
if (isOdd) rRepeat = mid == numsCopyed.get(n / 2 + 1);
for (int i = 0; i < n; i++) {
int diff = nums.get(i) - mid;
if (diff > 0) {
pw.print("0 ");
} else if (diff == 0 && isOdd && lRepeat) {
pw.print("1 ");
} else if (diff == 0 && isOdd && !lRepeat) {
pw.print("0 ");
} else if (diff == 0 && !isOdd && lRepeat && lRepeatTwo) {
pw.print("1 ");
} else if (diff == 0 && !isOdd) {
pw.print("0 ");
} else if (diff < 0 && isOdd && rRepeat) {
pw.print(-diff + " ");
} else if (diff < 0 && isOdd && !rRepeat) {
pw.print(-diff + 1 + " ");
} else if (diff < 0 && !isOdd && !lRepeat) {
pw.print(-diff + " ");
} else if (diff < 0 && !isOdd && lRepeat) {
pw.print(-diff + 1 + " ");
}
}
}
}
试题 E: 求阶乘
[题解]
n! 后面有几个零,意味着求 n! 中 5 的质因子有多少个
import java.io.*;
import java.util.*;
import java.math.*;
import java.util.stream.*;
/**
* 2022 求阶乘 二分枚举 质因数分解
*
*/
public class Main {
static BufferedReader br;
static PrintWriter pw;
public static void main(String[] args) throws Exception{
br = new BufferedReader(new InputStreamReader(System.in));
pw = new PrintWriter(new OutputStreamWriter(System.out));
new Main().go();
pw.flush();
}
void go() throws Exception{
long k = Long.parseLong(br.readLine());
long left = k, right = 5 * k;
while(left + 1 < right) {
long mid = left + (right - left) / 2;
if (cal(mid) >= k) {
right = mid;
} else {
left = mid;
}
}
if (cal(right) != k) {
pw.print(-1);
} else {
pw.print(right);
}
}
long cal(long n) {
if (n < 5) return 0;
return n / 5 + cal(n / 5);
}
}
试题 F: 最大子矩阵
[题解]
import java.io.*;
import java.util.*;
/**
* 2022 最大子矩阵 预处理 滑动窗口 单调队列 二维一维化
*
*/
public class Main {
static BufferedReader br;
static StreamTokenizer st;
static PrintWriter pw;
public static void main(String[] args) throws Exception{
br = new BufferedReader(new InputStreamReader(System.in));
st = new StreamTokenizer(br);
pw = new PrintWriter(new OutputStreamWriter(System.out));
new Main().go();
pw.flush();
}
int nextInt() throws Exception{
st.nextToken();
return (int)st.nval;
}
int n,m;
int[][] matrix;
int limit;
int[][][] maxColumn;
int[][][] minColumn;
void go() throws Exception{
n = nextInt();
m = nextInt();
matrix = new int[n][m];
maxColumn = new int[m][n][n];
minColumn = new int[m][n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i][j] = nextInt();
}
}
limit = nextInt();
// 预处理维护 i 列 [j,k] 行最值
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
for (int k = j; k < n; k++) {
if (k == j) {
maxColumn[i][j][k] = matrix[k][i];
minColumn[i][j][k] = matrix[k][i];
} else {
maxColumn[i][j][k] = Math.max(matrix[k][i], maxColumn[i][j][k - 1]);
minColumn[i][j][k] = Math.min(matrix[k][i], minColumn[i][j][k - 1]);
}
}
}
}
int ans = 1;
for(int r1 = 0; r1 < n; r1++) {
for(int r2 = r1; r2 < n; r2++) {
ans = Math.max(ans, longestSubarray(r1, r2) * (r2 - r1 + 1));
}
}
pw.print(ans);
}
// 得到行最大子矩阵,注意有可能找不到符合要求的
int longestSubarray(int r1, int r2) {
int l = 0, res = 0;
// 记录窗口最小值
Deque<Integer> minQueue = new LinkedList<>();
// 记录窗口最大值
Deque<Integer> maxQueue = new LinkedList<>();
for (int i = 0; i < m; i++) {
// 保证最小值队列单调递增
while (!minQueue.isEmpty() && minQueue.peekLast() > minColumn[i][r1][r2]) minQueue.pollLast();
minQueue.addLast(minColumn[i][r1][r2]);
// 保证最大值队列单调递减
while (!maxQueue.isEmpty() && maxQueue.peekLast() < maxColumn[i][r1][r2]) maxQueue.pollLast();
maxQueue.addLast(maxColumn[i][r1][r2]);
if (maxQueue.peek() - minQueue.peek() > limit) {
while (!minQueue.isEmpty() && !maxQueue.isEmpty() && maxQueue.peek() - minQueue.peek() > limit) {
if (minColumn[l][r1][r2] == minQueue.peek()) minQueue.pollFirst();
if (maxColumn[l++][r1][r2] == maxQueue.peek()) maxQueue.pollFirst();
}
}
res = Math.max(res, i - l + 1);
}
return res;
}
}
试题 G: 数组切分
[题解]
首先明确一点:该子数组是否切分正确可通过比较该子数组的长度与该子数组的最大值 - 最小值 + 1 是否相等,若相等则切分正确,反之切分错误。
①先提供一种便于理解,但会 TLE 的回溯算法
回溯枚举了所有情况,满足条件才会 res++
import java.io.*;
import java.util.*;
import java.math.*;
import java.util.stream.*;
/**
* 2022 数组切分
*/
public class Main {
public static void main(String[] args) throws Exception {
new Main().go();
}
static BufferedReader br;
static StreamTokenizer st;
static PrintWriter pw;
private void go() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
st = new StreamTokenizer(br);
pw = new PrintWriter(new OutputStreamWriter(System.out));
getAns();
pw.flush();
}
private int nextInt() throws Exception {
st.nextToken();
return (int) st.nval;
}
static final int N = 10010;
static final int MOD = (int)1e9 + 7;
int[] a = new int[N];
int n;
private void getAns() throws Exception {
n = nextInt();
for (int i = 1; i <= n; i++) {
a[i] = nextInt();
}
dfs(1);
pw.println(res);
}
int res = 0;
private void dfs(int i) {
int max = a[i];
int min = a[i];
if (i == n + 1) {
res = (res + 1) % MOD;
return;
}
for (int j = i; j <= n; j++) {
max = Math.max(max, a[j]);
min = Math.min(min, a[j]);
if (j - i == max - min) {
dfs(j + 1);
}
}
}
}
② dp
定义状态 f(i) 为以 i 结尾所有切分合法的方法数
import java.io.*;
import java.util.*;
import java.math.*;
import java.util.stream.*;
/**
* 2022 数组切分
*/
public class Main {
public static void main(String[] args) throws Exception {
new Main().go();
}
static BufferedReader br;
static StreamTokenizer st;
static PrintWriter pw;
private void go() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
st = new StreamTokenizer(br);
pw = new PrintWriter(new OutputStreamWriter(System.out));
getAns();
pw.flush();
}
private int nextInt() throws Exception {
st.nextToken();
return (int) st.nval;
}
static final int N = 10010;
static final int MOD = (int)1e9 + 7;
int[] a = new int[N];
int n;
int[] f = new int[N];
private void getAns() throws Exception {
n = nextInt();
for (int i = 1; i <= n; i++) {
a[i] = nextInt();
}
f[0] = 1;
for (int i = 1; i <= n; i++) {
int max = a[i], min = a[i];
for (int j = i; j <= n; j++) {
max = Math.max(max, a[j]);
min = Math.min(min, a[j]);
if (max - min == j - i) {
// 证明 [i, j] 是段合法可切分区间
// 那么原先已经存在 f(i - 1) 应该加入到 f(j) 来
// 那么应该更新 f(j) = f(j) + f(i - 1)
f[j] = (f[j] + f[i - 1]) % MOD;
}
}
}
pw.println(f[n]);
}
}
试题 H: 回忆迷宫
[题解]
import java.io.*;
import java.util.Arrays;
/**
* 2022 回忆迷宫 模拟 dfs
* 由于刚开始不知道,迷宫形状如何,开一个尽可能大的数组去存放迷宫
* 存放的数组中 0 表示迷宫外围 1 表示迷宫空地 2 表示墙
*/
public class Main {
public static void main(String[] args) throws Exception {
new Main().go();
}
static BufferedReader br;
static StreamTokenizer st;
static PrintWriter pw;
private void go() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
st = new StreamTokenizer(br);
pw = new PrintWriter(new OutputStreamWriter(System.out));
getAns();
pw.flush();
}
private int nextInt() throws Exception {
st.nextToken();
return (int) st.nval;
}
static final int N = 110;
int[][] G = new int[2 * N + 1][2 * N + 1];
int xMin, yMin;
int row, column;
private void getAns() throws Exception {
int n = Integer.valueOf(br.readLine());
String s = br.readLine();
br.close();
s = " " + s;
char[] str = s.toCharArray();
// 迷宫空地
int x = N + 1, y = N + 1;
G[x][y] = 1;
for (int i = 1; i <= n; i++) {
char c = str[i];
if (c == 'U') {
x--;
G[x][y] = 1;
} else if (c == 'D') {
x++;
G[x][y] = 1;
} else if (c == 'L') {
y--;
G[x][y] = 1;
} else if (c == 'R') {
y++;
G[x][y] = 1;
}
}
// 迷宫的墙
for (int i = N + 1 - n; i <= N + 1 + n; i++) {
for (int j = N + 1 - n; j <= N + 1 + n; j++) {
if (G[i][j] == 1) {
if (G[i - 1][j] != 1) {
G[i - 1][j] = 2;
}
if (G[i + 1][j] != 1) {
G[i + 1][j] = 2;
}
if (G[i][j - 1] != 1) {
G[i][j - 1] = 2;
}
if (G[i][j + 1] != 1) {
G[i][j + 1] = 2;
}
}
}
}
// 找到应该迷宫所在的位置
xMin = Integer.MAX_VALUE;
yMin = Integer.MAX_VALUE; // 迷宫出现的最小行和列数
int xMax = Integer.MIN_VALUE, yMax = Integer.MIN_VALUE; // 迷宫最大行、列数
for (int i = N - n; i <= N + 2 + n; i++) {
int xFirst = -1, yFirst = -1;
boolean isFirst = true;
int yLast = -1;
for (int j = N - n; j <= N + 2 + n; j++) {
if (G[i][j] == 2) {
yLast = j;
if (isFirst) {
yFirst = j;
xFirst = i;
isFirst = false;
}
}
}
if (!isFirst) {
xMin = Math.min(xMin, xFirst);
yMin = Math.min(yMin, yFirst);
xMax = Math.max(xMax, xFirst);
yMax = Math.max(yMax, yLast);
}
}
row = xMax - xMin + 1;
column = yMax - yMin + 1;
// 将需要判断连通区域设置的大于原来的实际迷宫区域,保证迷宫空地都在一个连通块内
width = row + 2;
length = column + 2;
matrix = new int[width][length];
vis = new boolean[width][length];
for (int[] ints : matrix) {
Arrays.fill(ints, 0);
}
for (boolean[] vi : vis) {
Arrays.fill(vi, false);
}
// 由于上面的填充墙,只会围绕空地四周填充,内部实心墙不会填充
// 下面就是将剩余为填充的墙,填充完整
// 由于空地将整个区域化为两个连通块并且迷宫外围的连通块一定是率先遍历到的,我们这个连通块不要,剩下连通块都填充即可
wall();
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (G[xMin + i][yMin + j] == 0 && matrix[i + 1][j + 1] != 1)
G[xMin + i][yMin + j] = 2;
}
}
// 打印结果
for (int i = xMin, k = 0; i <= xMax; i++, k++) {
for (int j = yMin; j <= yMax; j++) {
if (G[i][j] == 1 || G[i][j] == 0) {
pw.print(" ");
} else if (G[i][j] == 2) {
pw.print("*");
}
}
pw.println();
}
}
int length, width;
int[][] matrix;
boolean[][] vis;
int order;
private void wall() {
for (int i = 0; i < width; i++) {
for (int j = 0; j < length; j++) {
if (G[xMin + i - 1][yMin + j - 1] == 0 &&!vis[i][j]) {
order++;
dfs(i, j);
}
}
}
}
private void dfs(int x, int y) {
if (x + 1 > width || x < 0 || y + 1 > length || y < 0 || vis[x][y]) return;
vis[x][y] = true;
if (G[xMin + x - 1][yMin + y - 1] != 0) return;
matrix[x][y] = order;
dfs(x + 1, y);
dfs(x - 1, y);
dfs(x, y + 1);
dfs(x, y - 1);
}
}
试题 I: 红绿灯
[题解]
import java.io.*;
import java.util.*;
import java.math.*;
import java.util.stream.*;
/**
* 2022 红绿灯 dp
* f(x, y) 表示到达第 x 个地方, 使用氮气加速需要冷却的红绿灯个数 y 特别记 x = 0 为起点, x = m + 1 为终点
*/
public class Main {
public static void main(String[] args) throws Exception {
new Main().go();
}
static BufferedReader br;
static StreamTokenizer st;
static PrintWriter pw;
private void go() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
st = new StreamTokenizer(br);
pw = new PrintWriter(new OutputStreamWriter(System.out));
getAns();
pw.flush();
}
private int nextInt() throws Exception {
st.nextToken();
return (int) st.nval;
}
static final int N = (int)10e8 + 10, M = 1010;
int n, m, k, v; // n 家到公司的距离 m 红绿灯个数 k 加速间隔的红绿灯个数 v 速度的倒数
long[] pos = new long[M], green = new long[M], red = new long[M]; // pos 起点、红绿灯、终点所在位置 green 绿灯持续时间 red 红灯持续时间
long[][] f = new long[M][M];
private void getAns() throws Exception {
n = nextInt();
m = nextInt();
k = nextInt();
v = nextInt();
pos[0] = 0;
pos[m + 1] = n;
for (int i = 1; i <= m; i++) {
pos[i] = nextInt();
green[i] = nextInt();
red[i] = nextInt();
}
f[0][0] = 0;
for (int i = 1; i <= k - 1; i++) {
// 定义非法数值取得要恰当些,要不然可能下面计算会导致数据溢出而使得答案错误
f[0][i] = Integer.MAX_VALUE;
}
for (int i = 1; i <= m + 1; i++) {
long intervalTime = (pos[i] - pos[i - 1]) * v;
// f[i][0] 由能开瞬移但不开瞬移和不能开瞬移取小转移得来
f[i][0] = intervalTime + Math.min(f[i - 1][0] + waitTime(i, f[i - 1][0] + intervalTime),
f[i - 1][1] + waitTime(i, f[i - 1][1] + intervalTime));
// j > 0 表示没法开瞬移,即 f[i][j] 由 f[i - 1][j + 1] 转移得到
for(int j = 1; j <= k - 2; j++) {
f[i][j] = f[i - 1][j + 1] + intervalTime + waitTime(i, f[i - 1][j + 1] + intervalTime);
}
// 开瞬移
f[i][k - 1] = f[i - 1][0] + waitTime(i, f[i - 1][0]);
}
long ans = Long.MAX_VALUE;
for (int i = 0; i <= k - 1; i++) {
ans = Math.min(ans, f[m + 1][i]);
}
pw.println(ans);
}
/**
* 计算出在红绿灯该等多久
* @param i
* @param time
* @return
*/
private long waitTime(int i, Long time) {
if (i > m) return 0;
// time % (green[i] + red[i]) 得到的值是该轮次红绿灯走的时间,若恰好等于 green[i] 说明红灯刚好亮
return time % (green[i] + red[i]) < green[i] ? 0 : red[i] - (time % (green[i] + red[i]) - green[i]);
}
}
试题 J: 拉箱子
[题解]
import java.io.*;
import java.util.*;
/**
* 2022 拉箱子 模拟
*/
public class Main {
public static void main(String[] args) throws Exception {
new Main().go();
}
static BufferedReader br;
static StreamTokenizer st;
static PrintWriter pw;
private void go() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
st = new StreamTokenizer(br);
pw = new PrintWriter(new OutputStreamWriter(System.out));
getAns();
pw.flush();
}
private int nextInt() throws Exception {
st.nextToken();
return (int) st.nval;
}
static final int N = 15;
int n, m;
int[][] grid = new int[N][N];
// 存储空地的坐标
List<Integer> list = new ArrayList<>();
int[] dx = {0, 1, 0, -1}, dy = {1, 0, -1, 0};
int[][][] arr = new int[N * N][4][2];
private void getAns() throws Exception {
n = nextInt();
m = nextInt();
for (int i = 1, idx = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
grid[i][j] = nextInt();
if (grid[i][j] == 0) {
grid[i][j] = idx++;
list.add(i * 100 + j);
} else if (grid[i][j] == 1) {
// -1 代表非法位置, 即这里有墙
grid[i][j] = -1;
}
}
}
int len = list.size();
for (int i = 1; i <= len; i++) {
// 初始化并查集
int[] father = new int[len + 1];
int[] size = new int[len + 1];
for (int j = 1; j <= len; j++) {
father[j] = j;
size[j] = 1;
}
// 合并连通区域
for (int j = 1; j <= len; j++) {
if (i == j) continue;
int x = list.get(j - 1) / 100, y = list.get(j - 1) % 100;
for (int k = 0; k < 2; k++) {
int nx = x + dx[k], ny = y + dy[k];
// 越界或无意义
if (nx < 1 || ny < 1 || nx > n || ny > m || grid[nx][ny] == -1 || grid[nx][ny] == i) continue;
int fa = find(father, j), fb = find(father, grid[nx][ny]);
if (fa != fb) {
father[fa] = fb;
size[fb] += size[fa];
}
}
}
// 得到一个点四周的连通情况
int x = list.get(i - 1) / 100, y = list.get(i - 1) % 100;
for (int j = 0; j < 4; j++) {
int nx = x + dx[j], ny = y + dy[j];
if (nx < 1 || ny < 1 || nx > n || ny > m || grid[nx][ny] == -1) continue;
int fx = find(father, grid[nx][ny]);
arr[i][j] = new int[]{fx, size[fx]};
}
}
int ans = 0;
for (int target = 1; target <= len; target++) {
int tx = list.get(target - 1) / 100, ty = list.get(target - 1) % 100;
for (int box = 1; box <= len; box++) {
if (box == target) continue;
int bx = list.get(box - 1) / 100, by = list.get(box - 1) % 100;
Set<Integer> set = new HashSet<>();
for (int i = 0; i < 4; i++) {
int nx = bx + dx[i], ny = by + dy[i];
if (nx < 1 || ny < 1 || nx > n || ny > m || grid[nx][ny] == -1) continue;
int block = arr[box][i][0];
if (!set.contains(block) && bfs(tx, ty, bx, by, i)) {
set.add(block);
ans += arr[box][i][1];
// 判断人是否有可能占据了终点的位置
if (isConnected(bx, by, tx, ty, nx, ny)) ans--;
}
}
}
}
pw.println(ans);
}
private boolean isConnected(int bx, int by, int tx, int ty, int fx, int fy) {
boolean[][] vis = new boolean[n + 1][m + 1];
Queue<int[]> queue = new ArrayDeque<>();
queue.add(new int[]{fx, fy});
while (!queue.isEmpty()) {
int[] tmps = queue.poll();
int x = tmps[0], y = tmps[1];
if (x == tx && y == ty) return true;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 1 || ny < 1 || nx > n || ny > m || (bx == nx && by == ny) || grid[nx][ny] == -1 || vis[nx][ny])
continue;
vis[nx][ny] = true;
queue.add(new int[]{nx, ny});
}
}
return false;
}
// 判断这个位置的箱子能否到达终点
private boolean bfs(int tx, int ty, int bx, int by, int dir) {
boolean[][][] vis = new boolean[n + 1][m + 1][4];
Queue<int[]> queue = new ArrayDeque<>();
queue.add(new int[]{bx, by, dir});
vis[bx][by][dir] = true;
while (!queue.isEmpty()) {
int[] tmps = queue.poll();
int x = tmps[0], y = tmps[1], d = tmps[2];
if (x == tx && y == ty) return true;
// 直走
// 箱子的下一个位置
int nx = x + dx[d], ny = y + dy[d];
if (nx + dx[d] > 0 && nx + dx[d] <= n && ny + dy[d] > 0 && ny + dy[d] <= m // 人不出界
&& grid[nx + dx[d]][ny + dy[d]] != -1 // 人的位置不是墙
&& !vis[nx][ny][d]) {
vis[nx][ny][d] = true;
// 箱子合法位置入队
queue.add(new int[]{nx, ny, d});
}
int b = arr[grid[x][y]][d][0];
// 转弯
for (int i = 0; i < 4; i++) {
if (i == d) continue;
// 满足人可以到达箱子要转弯的位置,才合法
if (arr[grid[x][y]][i] != null && arr[grid[x][y]][i][0] == b && !vis[x][y][i]) {
vis[x][y][i] = true;
// 满足转弯条件入队
queue.add(new int[]{x, y, i});
}
}
}
return false;
}
private int find(int[] father, int x) {
if (father[x] == x) return x;
int fx = find(father, father[x]);
father[x] = fx;
return fx;
}
}
以上综合各位大佬提供给的思路和我自己的思路,自己写出的题解。