题目大意: 输入一个p*q的棋盘, 行用数字表示, 列用大写字母表示 , 1 <= p*q <= 26, 输出能够把棋盘全部空格走完且每个空格只走一次的字典序最小的路径。不存在则输出“impossible”
坑の所在: 行列的表示, 每组解后有一空行。
思路: 八方向dfs,方向数组要按字典序排列, 记录步数, 最先找到的一组解便是字典序最小解,便可停止搜索。
AC代码:
#include<iostream>
#include<cstdio>
using namespace std;
int p, q;
bool vis[30][30];
int d[8][2] = { -1,-2, 1,-2, -2,-1, 2,-1, -2,1, 2,1, -1,2, 1, 2 };
struct node{
int x, y;
}next[30][30];
bool check(int a, int b)
{
if(a >= 0 && a < p && b >= 0 && b < q) return true;
return false;
}
bool stop;
void init()
{
for(int i = 0; i < 30; i++)
for(int k = 0; k < 30; k++){
vis[i][k] = false;
next[i][k].x = next[i][k].y = -1;
}
vis[0][0] = true;
stop = 0;
}
void dfs(int a, int b, int step)
{
if(step == p*q) {
stop = true;
return;
}
for(int i = 0; i < 8; i++){
int dx = a + d[i][0];
int dy = b + d[i][1];
if(check(dx, dy) && !vis[dx][dy]){
next[a][b].x = dx;
next[a][b].y = dy;
vis[dx][dy] = true;
//cout<<a<<" "<<b<<" "<<next[a][b].x<<" "<<next[a][b].y<<endl;
dfs(dx, dy, step+1);
if(stop) return;
vis[dx][dy] = false;
}
}
}
void output()
{
int a = 0, b = 0, t, step = 1;
printf("%c%d", a+'A', b+1);
while(step < p*q){
printf("%c%d", next[a][b].y+'A', next[a][b].x+1);
t = a;
a = next[a][b].x;
b = next[t][b].y;
step++;
}
printf("\n");
}
int main()
{
int T;
cin>>T;
for(int k = 1; k <= T; k++){
scanf("%d%d", &p, &q);
init();
dfs(0, 0, 1);
printf("Scenario #%d:\n", k);
if(stop) output();
else printf("impossible\n");
if(k != T)printf("\n");
}
return 0;
}