题目:
![](https://img-blog.csdnimg.cn/img_convert/4f895d2292396fdd6854a77cd8856963.png)
小明冒充X星球的骑士,进入了一个奇怪的城堡。
城堡里边什么都没有,只有方形石头铺成的地面。
假设城堡地面是 n x n 个方格。如上图所示。
按习俗,骑士要从西北角走到东南角。
可以横向或纵向移动,但不能斜着走,也不能跳跃。
每走到一个新方格,就要向正北方和正西方各射一箭。
(城堡的西墙和北墙内各有 n 个靶子)
同一个方格只允许经过一次。但不必走完所有的方格。
如果只给出靶子上箭的数目,你能推断出骑士的行走路线吗?
有时是可以的,比如上图中的例子。
本题的要求就是已知箭靶数字,求骑士的行走路径(测试数据保证路径唯一)
输入:
第一行一个整数N(0<N<20),表示地面有 N x N 个方格
第二行N个整数,空格分开,表示北边的箭靶上的数字(自西向东)
第三行N个整数,空格分开,表示西边的箭靶上的数字(自北向南)
输出:
一行若干个整数,表示骑士路径。
为了方便表示,我们约定每个小格子用一个数字代表,从西北角开始编号: 0,1,2,3....
比如,上图中的方块编号为:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
eg:
![](https://img-blog.csdnimg.cn/img_convert/910423d44a7da68e097ba13cb7d89bf1.png)
代码写的注释挺详细的,直接看代码吧,代码如下:
#include<iostream>
using namespace std;
int n; // n * n 个方格 ,0<n<20
int a[20],b[20]; //a为自西向东的靶数,b为自北向南的靶数
int arr[20][20]; //构建二维数组,代表格子
int vis[20][20] = {0}; // 标记此点是否被走过,每个点只能走一次
int top; //栈顶
int stack[20]; //调用栈,储存路径(最终经过的路程,即答案)
int dx[4] = {1,0,-1,0}; //以中间为中心点,代表方向坐标,对应下左上右
int dy[4] = {0,-1,0,1}; //下左上右,如图
//检查靶子上的靶数 是否为0,为0路径正确,否则路径不正确
bool check() {
for(int i=0; i<n; i++) {
if(a[i] != 0 || b[i] != 0) {
return false;
}
return true;
}
}
void dfs(int x,int y,int step) {
//如果要射的箭数<0,说明多射了一箭,再走下去是不对的
if(a[y]<0||b[x]<0)
return;
//终止条件 ,到达最后一个格子,坐标为(n-1,n-1)
if(x==n-1&&y==n-1) {
//靶数对应正确则输出,否则继续递归
if(check()) {
for(int i=0; i<top; i++)
cout<<stack[i]<<"";
cout<<endl;
}
return ;
}
//判断下一步方向,共四个方向
for(int i=0; i<4; i++) {
int tx,ty; //下一点的坐标
tx=x+dx[i];
ty=y+dy[i];
//未被访问且超出格子
if(vis[tx][ty]==0&&tx>=0&&tx<n&&ty>=0&&ty<n) {
vis[tx][ty] = 1; //标记为访问
stack[top++] = arr[tx][ty]; //格子对应标记入栈
a[ty]--; //靶数对应减1
b[tx]--;
dfs(tx, ty, step+1); //从当前坐标继续向后走(递归调用)
a[ty]++; //回溯(靶数对应加1)
b[tx]++;
top--; //出栈
vis[tx][ty] = 0; //标记为未访问
}
}
}
int main() {
cin >> n;
//输入靶数
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++)
cin >> b[i];
//初始化格子标记0,1,2,3,4,...,n-1
for (int i = 0,k=0; i < n; i++)
for (int j = 0; j < n; j++)
arr[i][j] = k++;
//从第一个格子开始,将第一个格子做一些初始化
vis[0][0] = 1; //标记为访问
stack[0] = arr[0][0]; //入栈
top = 1; //栈内元素个数为1
a[0]--; //对应靶数减1
b[0]--;
dfs(0, 0, 1); //从坐标(0,0)开始向后走
return 0;
}
代码注释中提到的图如下图所示:
![](https://img-blog.csdnimg.cn/img_convert/5811058d746123970b3fda50948da37b.png)
右下角还有一个方块,整个是个长方体的形状,大家自行脑补