问题描述
林克驰骋在海拉鲁大陆的平原上无比自由,他想起二维空间中的国际象棋同伴,回想起自己也活在2D世代的局限,心生怜悯。
那些骑士,永远被局限在8×8的棋盘之内厮杀,他们的世界永不改变。因此,林克去到阿卡来研究所寻求帮助,他得到新的道具——变形棋盘。
这个变形棋盘可以根据输入的两个参数的(p,q)创造全新的棋盘空间。
如下图分别是(p,q)为(3,9) , (6,3) ,以及(5,5)的棋盘空间。
请问对于每一种棋盘(p,q),2D骑士是否有一种一次遍历所有棋盘方格的路线?
如果有,请输出这条路线(若有多条路线,请输出字典序最小的路线)。
如果没有,请输出无。
输入
输入数据第一行为正整数n,代表有多少组输入样例
接下来n行是两个整数代表行p和列q, 代表变形棋盘的行列参数,其中(1 <= p * q <= 26)。
样例
5
5 1
5 2
5 3
5 4
5 5
输出
每个样例的输出2行,格式如下:
"#i:" 其中i代表第i种棋盘
骑士跳过的每个格子(每个访问的格子用大写字母加数字表示),一条可行的路径输出如(A1B3C1A2B4C2A3B1C3A4B2C4),
如果没有可行方案,则第二行输出:none
样例
#1: none #2: none #3: none #4: A1B3A5C4D2B1A3B5D4C2B4A2C1D3C5A4B2D1C3D5 #5: A1B3A5C4A3B1D2E4C5A4B2D1C3B5D4E2C1A2B4D5E3C2E1D3E5
思路
我们很容易看出来可以用深度优先搜索来解决这个问题。我们先声明一个足够大的二维数组作为棋盘,然后遍历每个格子作为起点,利用方向向量进行深度优先搜索,如果找到了一条路径,我们就把它存到答案中,并结束搜索。如果遍历了所有格子作为起点搜索后仍然没有找到一条路径,则说明无解,输出none。
注意事项
- 方向向量的遍历顺序一定要和题目所给的顺序一致。
- 解答每个样例之前,都要清空答案。
- 在找到一条路径后不能继续递归,否则会导致超时。
- 注意对应二维数组的行列和棋盘的行列。
代码实现
深搜函数和一些全局变量。
#include<iostream>
#include<vector>
using namespace std;
int dx[8] = { -2,-2,-1,-1,1,1,2,2 };//方向向量,注意行列,且顺序一定要和题目一致
int dy[8] = { -1,1,-2,2,-2,2,-1,1 };
int che[27][27];//声明全局二维数组作为棋盘
int r, c;
int flag = 1;
vector<pair<int, int>> path;
vector<pair<int, int>> res;
bool check() {//检查棋盘上是否每个格子都被走过
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= c; j++)
if (che[i][j] != 1)
return false;//如果有格子没被走过,返回false
}
return true;//否则,返回true
}
void dfs(int x,int y) {//深搜函数
che[y][x] = 1;//把起点标记为1,表示已走过
path.push_back({ x,y });
if (check()&&flag)//如果是第一次全部走完棋盘,则把本次路径放入答案中
{
flag = 0;//把flag标记为0,后续不再回溯搜索了
res.operator=(path);
return;
}
for (int i = 0; i < 8; i++) {//如果棋盘还没走完,就继续走
int nx = x + dx[i];//注意走格子的顺序一定要和题目给的顺序一致
int ny = y + dy[i];
if (nx >= 1 && nx <= c && ny >= 1 && ny <= r&&che[ny][nx]!=1) {
//如果找到一个合法且没有走过的格子
if (flag)//如果还没找到过答案
dfs(nx, ny);//递归继续向深处搜索
else
break;//否则,直接退出循环
}
}
che[y][x] = 0;//回溯,探索另一种走法
path.pop_back();
}
加上主函数,问题解决。
int main() {
int n;
cin >> n;//n个测试样例
for (int i = 0; i < n; i++) {
flag = 1;
res.clear();//搜索之前先清空答案
cin >> r >> c;
for (int j = 1; j <= r; j++) {
for (int k = 1; k <= c; k++)
{
//遍历棋盘的每个格子,分别作为起点
path.clear();//搜索之前,清空路径
dfs(k, j);//开始搜索
}
}
cout << "#" << i + 1 <<":"<< endl;
if (res.empty()) {//如果没找到解输出none
cout << "none" << endl;
}
else{//否则输出路径
for (auto it = res.begin(); it != res.end(); it++) {
printf("%c%d", it->first + 'A' - 1, it->second);
}
cout << endl;
}
}
}