题意:
一个骑士无聊了,于是进行世界旅行,他的世界是一个矩形棋盘,当他移动的时候,先向一个方向走两个,再在垂直的方向上走一格,不能走出棋盘,我们的任务是找到一条路径,骑士走遍所有的格子,每个走一次,如果有那么一条路,把路径输出,横坐标按字母表顺序从小到大,纵坐标按数字顺序从小到大。如果没有输出“impossible”。
思路:
1. dfs + 回溯。深度遍历去寻找一个可行的路径,如果某一条路径行不通,则回溯,把一些标志位去掉。
2. 如果最终走得通,则吧 succ 位设置 true,由于路径是对于字典序排的,所以对于剩下的情况不作处理,直接 return 即可。
3. 对于路径的压栈、出栈操作比较出彩,几个标志位的设置如 PC, succ也很漂亮。
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 50;
const int MAXC = 2 * MAXN * MAXN;
bool vis[MAXN][MAXN], succ;
char path[MAXC];
int P, Q, PC;
int dir[8][2] = {-2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1};
bool judge(int x, int y) {
if (x > 0 && x <= Q && y > 0 && y <= P && !vis[x][y]) {
return true;
}
return false;
}
void dfs(int x, int y) {
if (succ)
return ;
vis[x][y] = true;
path[PC++] = x + 'A' - 1;
path[PC++] = y + '0';
if (PC == P * Q * 2) {
succ = true ;
return ;
}
for (int i = 0; i < 8; ++i) {
int newx = x + dir[i][0];
int newy = y + dir[i][1];
if (judge(newx, newy) && !succ) {
dfs(newx, newy);
PC -= 2;
vis[newx][newy] = false;
}
}
}
int main()
{
int cases, cc = 0;
scanf("%d", &cases);
while (cases--) {
scanf("%d%d", &P, &Q);
memset(vis, false, sizeof(vis));
memset(path, 0, sizeof(path));
PC = 0, succ = false;
dfs(1, 1);
if (succ) {
printf("Scenario #%d:\n%s\n\n", ++cc, path);
} else {
printf("Scenario #%d:\nimpossible\n\n", ++cc);
}
}
return 0;
}