本题是一个比较基础的DFS问题,但是坑点也有很多
1.字典序输出 2.如何处理输出过程中的字母的输出问题
AC后的恍然大悟:
本题要求的是棋盘的所有位置都必须经过一遍,且搜索是无方向性的。所以无论从哪个点开始,我们都必须经过每一点一次。(因此深搜只需一次)
而字典序最小的当然是从最左上角开始咯,我们只需要从(1,1)点开始深搜使所有点都被搜了一遍即可。如果无法搜完全部点,则impossible,否则输出
技巧:本题使用方向向量确定深搜的8个位置,注意,我们要将8个位置按照字典序大小排序,方便搜索时直接按序搜索即可
贴下AC代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N = 30;
//方向向量
int dx[8] = {-1, 1, -2, 2, -2, 2, -1, 1};
int dy[8] = {-2, -2, -1, -1, 1, 1, 2, 2};
//是否可以搜完的标志
bool flag;
//每达一点则该点被置为不可再被搜
bool st[N][N];
//每次搜索的点的位置表示
struct Path{
char x;
char y;
}path[N];
void dfs(int ux, int uy, int p, int q, int num){
path[num].x = ux + '0';
path[num].y = uy + 'A' - 1;
if(num == p * q){
flag = true;
return ;
}
for(int i = 0; i < 8; i++){
int x = ux + dx[i], y = uy + dy[i];
if(x > 0 && x <= p && y > 0 && y <= q && st[x][y] == false && flag == false){
st[x][y] = true;
dfs(x, y, p, q, num + 1);
st[x][y] = false;
}
}
}
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++){
//每次新的测试数据的初始化
flag = false;
memset(st, false, sizeof(st));
st[1][1] = true;
int p, q;
cin >> p >> q;
//从最左上角开始深搜
dfs(1, 1, p, q, 1);
cout << "Scenario #" << i << ":\n";
if(flag){
for(int j = 1; j <= p * q; j++) cout << path[j].y << path[j].x;
cout << "\n";
}
else
cout << "impossible" << "\n";
if(i != n) cout << "\n";
}
return 0;
}