蓝桥杯 国赛真题 路径之谜 DFS+剪枝

🍑 算法题解专栏


🍑 路径之谜

在这里插入图片描述
在这里插入图片描述
输入

4
2 4 3 4
4 3 3 3

输出

0 4 5 1 2 3 7 11 10 9 13 14 15

🍑 思路
🍤 数据范围 20 直接暴力搜索所有路径
🍤 剪枝:特判掉不可能的方案(20% --> 100%)

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

import java.util.*;

public class Main
{
	static int N = 25;
	static int[][] a;// 地图
	static boolean[][] st = new boolean[N][N];// 去重状态数组
	static int[] bx, by;// 分别表示靶子上箭的数量
	static LinkedList<Integer> path = new LinkedList<>();// 记录路径
	static int n;

	static int[] dx = { 0, 1, 0, -1 };
	static int[] dy = { 1, 0, -1, 0 };

	static void dfs(int x, int y)// x y 表示当前位置的下标
	{
//		递归出口
		if (x == n - 1 && y == n - 1)
		{
			if (check())
			{
				for (int it : path)
					System.out.print(it + " ");
				System.exit(0);
			}
			return;
		}

		for (int i = 0; i < 4; i++)
		{
			int xx = x + dx[i];
			int yy = y + dy[i];
//			System.out.println("bug");
			if (xx >= 0 && xx < n && yy >= 0 && yy < n && !st[xx][yy] && bx[xx] > 0 && by[yy] >0)//剪掉靶子已经射满箭的枝
			{
				bx[xx]--;
				by[yy]--;
				st[xx][yy] = true;
				path.add(a[xx][yy]);
				dfs(xx, yy);
//				回溯
				bx[xx]++;
				by[yy]++;
				st[xx][yy] = false;
				path.removeLast();
			}
		}

	}

	private static boolean check()
	{
//		System.out.println("bug");
		for (int i = 0; i < n; i++)
		{
			if (bx[i] != 0 || by[i] != 0)
				return false;
		}
		return true;
	}

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		a = new int[n][n];
		bx = new int[n];
		by = new int[n];
		Arrays.fill(bx, 0);
		Arrays.fill(by, 0);
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				a[i][j] = i * n + j;

		for (int i = 0; i < n; i++)
			by[i] = sc.nextInt();// 列号即北边的靶子号

		for (int i = 0; i < n; i++)
			bx[i] = sc.nextInt();// 行号即北边的靶子号

		bx[0]--;
		by[0]--;
		st[0][0] = true;
		path.add(0);
		dfs(0, 0);
	}
}
posted @ 2023-04-24 13:55  兑生  阅读(32)  评论(0编辑  收藏  举报  来源
Live2D