P8642 [蓝桥杯 2016 国 AC] 路径之谜 题解
数据范围很小,考虑爆搜。
搜到位置 $(x,y)$ 时统计 $(x,y)$ 的贡献,即 $x$ 行与 $y$ 列的箭靶箭数减一。
容易发现,若此时 $x$ 行或 $y$ 列的箭靶箭数为 $0$,则不能走到 $x,y$,不需要往下搜。(可行性剪枝)
搜索时记录 $z_i$ 表示第 $i$ 步的位置,搜到终点后输出 $z$ 即可。
#include <cstdio>
#include <cstdlib>
int n, o, p[20], q[20], z[450], f[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
bool v[20][20];
void D(int x, int y, int d)
{
if (x < 0 || x >= n || y < 0 || y >= n || v[x][y] || !p[x] || !q[y])
return;
v[x][y] = 1;
--p[x];
--q[y];
z[d] = x * n + y;
if (x == n - 1 && y == n - 1)
{
if (d == o)
{
for (int i = 1; i <= d; ++i)
printf("%d ", z[i]);
exit(0);
}
}
else
for (int i = 0, a, b; i < 4; ++i)
D(x + f[i][0], y + f[i][1], d + 1);
v[x][y] = 0;
++p[x];
++q[y];
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; ++i)
scanf("%d", q + i), o += q[i];
for (int i = 0; i < n; ++i)
scanf("%d", p + i);
D(0, 0, 1);
}