import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
static int[] dx = {
1, -1, 0, 0 };
static int[] dy = {
0, 0, 1, -1 };
static int[] numsi;
static int[] numsj;
static int n;
static Deque<Integer> stack = new LinkedList<>();
static Deque<Integer> res = new LinkedList<>();
蓝桥杯和 leetcode 不同在于:
蓝桥杯要求实现全部代码(整个Main类),leetcode 要求实现某个函数。
所以在蓝桥杯中,一些 函数变量 的传递可以直接作为 类的成员变量 进行传递。
变量说明:
int[] dx, dy
:因为要往 4 个方向 dfs,以这种数组形式非常方便。numsi, numsj
:记录靶子数stack
:记录过程中的路径;res
:记录答案路径
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 在此输入您的代码...
n = scan.nextInt();
numsi = new int[n];
numsj = new int[n];
for (int i = 0; i < n; i++) {
numsj[i] = scan.nextInt();
}
for (int i = 0; i < n; i++) {
numsi[i] = scan.nextInt();
}
int[][] path = new int[n][n];
dfs(path, 0, 0); //正是因为将变量全部定义到成员变量中 这里才会如此简洁。
while (!res.isEmpty()) {
System.out.print(res.removeLast() + " ");
}
scan.close();
}
private static void dfs(int[][] path, int i, int j) {
if (!isArea(i, j))
return;
if (path[i][j] == 1)
return;
for (int k = 0; k < 4; k++) {
int ti = i + dx[k];
int tj = j + dy[k];
if (numsi[i] - 1 >= 0 && numsj[j] - 1 >= 0) {
numsi[i] = numsi[i] - 1;
numsj[j] = numsj[j] - 1;
path[i][j] = 1;
// (i, j) => n * i + j
stack.push(n * i + j);
if (i == n - 1 && j == n - 1 && noZero(numsi) && noZero(numsj)) {
res = new LinkedList<>(stack);
return;
}
dfs(path, ti, tj);
//回溯:将所有状态还原
numsi[i] = numsi[i] + 1;
numsj[j] = numsj[j] + 1;
path[i][j] = 0;
stack.pop();
}
}
}
private static boolean noZero(int[] numsi) {
for (int i = 0; i < n; i++) {
if (numsi[i] != 0)
return false;
}
return true;
}
private static boolean isArea(int i, int j) {
return 0 <= i && i < n && 0 <= j && j < n;
}
}
关于该 if
语句的位置:
if (i == n - 1 && j == n - 1 && noZero(numsi) && noZero(numsj)) {
res = new LinkedList<>(stack);
//res.addFirst(n * i + j);
return;
}
如果放在 dfs
函数的开头(for
循环前),那么就会有一个问题:
此时,
numsi
和numsj
最后一个元素并没有-1
,栈stack
也并没有将n*i+j
压入栈。
这就会导致:在使用 noZero
判断时,最后一个元素需要单独判断且是1
,且 res
需要单独将n*i+j
压入栈。
综上,写在 for
循环内。