【路径之谜】dfs

路径之谜

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 要求实现某个函数。

所以在蓝桥杯中,一些 函数变量 的传递可以直接作为 类的成员变量 进行传递。

变量说明:

  1. int[] dx, dy:因为要往 4 个方向 dfs,以这种数组形式非常方便。
  2. numsi, numsj:记录靶子数
  3. 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 循环前),那么就会有一个问题:

此时,numsinumsj 最后一个元素并没有-1,栈stack也并没有将n*i+j压入栈。

这就会导致:在使用 noZero 判断时,最后一个元素需要单独判断且是1,且 res 需要单独将n*i+j压入栈。

综上,写在 for 循环内。

猜你喜欢

转载自blog.csdn.net/m0_60641871/article/details/129969727