蓝桥杯 国赛真题 路径之谜 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);
}
}