题目描述
小明冒充 X 星球的骑士,进入了一个奇怪的城堡。
城堡里边什么都没有,只有方形石头铺成的地面。
假设城堡地面是 n×n 个方格。如下图所示。
按习俗,骑士要从西北角走到东南角。可以横向或纵向移动,但不能斜着走,也不能跳跃。每走到一个新方格,就要向正北方和正西方各射一箭。(城堡的西墙和北墙内各有 n 个靶子)同一个方格只允许经过一次。但不必走完所有的方格。如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?有时是可以的,比如上图中的例子。
本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)
输入描述
第一行一个整数 N (0≤N≤20),表示地面有 N×N 个方格。
第二行 N 个整数,空格分开,表示北边的箭靶上的数字(自西向东)
第三行 N 个整数,空格分开,表示西边的箭靶上的数字(自北向南)
输出描述
输出一行若干个整数,表示骑士路径。
为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号: 0,1,2,3 ⋯⋯
比如,上图中的方块编号为:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
输入输出样例
示例
输入
4
2 4 3 4
4 3 3 3
输出
0 4 5 1 2 3 7 11 10 9 13 14 15
运行限制
- 最大运行时间:5s
- 最大运行内存: 256M
#include<iostream>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<list>
using namespace std;
typedef long long ll;
const ll MAX = 1e2;
ll map[MAX][MAX];//存储地图编号
ll f[MAX][MAX];//是否已经走过
ll north[MAX], west[MAX];//北和西箭靶
ll path[MAX];//路径
void dfs(ll n,ll x,ll y,ll id)
{
if (x<1 || y<1 || x>n || y>n)//边界
{
return;
}
if (f[x][y] == 1)//已走过的路线
{
return;
}
if (north[y] > 0 && west[x] > 0)//是否可以射箭
{
north[y]--;
west[x]--;
f[x][y] = 1;
path[id] = map[x][y];
if (x == n && y == n)//到达终点
{
ll sum = 0;
for (int i = 1; i <= n; i++)
{
sum += north[i];
}
for (int i = 1; i <= n; i++)
{
sum += west[i];
}
if (sum == 0)//是否剩余箭靶没有射
{
for (int i = 1; i <= id; i++)
{
cout << path[i] << " ";
}
return;
}
}
dfs(n, x + 1, y, id + 1);//下
dfs(n, x, y + 1, id + 1);//右
dfs(n, x - 1, y, id + 1);//上
dfs(n, x, y - 1, id + 1);//左
north[y]++;
west[x]++;//箭靶恢复未走过的状态
f[x][y] = 0;//标记记为0
path[id] = 0;//路径清空
//返回上一层
}
}
int main()
{
ll n;
cin >> n;
ll k = 0;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
map[i][j] = k++;
}
}
for (int i = 1; i <= n; i++)
{
cin >> north[i];
}
for (int i = 1; i <= n; i++)
{
cin >> west[i];
}
path[1] = 0;
dfs(n,1,1,1);
return 0;
}