题目大意:
考察马能否周游一遍棋盘上所有的格子一遍(不重复经过同一个格子),有t个测例,每个测例都会给出棋盘大小p×q,其中1 ≤ pq ≤ 26,其中p表示的棋盘的行(1 ~ 8),q表示棋盘的列数(A ~ A+q-1),对于每个测例如果可以周游就输出一条周游路线,路线中先后包括一路上经过的格子的代号,比如"A1B2E4"就代表先后经过了1行A列、2行B列、4行E列,如果存在多条路线,则输出字典序最小的那条路线,如果不存在则输出"impossible"。
注释代码:
/*
* Problem ID : POJ 2488 A Knight's Journey
* Author : Lirx.t.Una
* Language : C++
* Run Time : 0 ms
* Run Memory : 132 KB
*/
#include <iostream>
#include <cstring>
#include <cstdio>
//棋盘最大宽度(3×9=27>26)
#define MAXW 8
//最大周游步数25步
#define MAXSTP 26
//程序中行为字母,列为数字
int r, c;//棋盘的行数和列数
int stp;//当前马做过的步数
bool vis[MAXW][MAXW];//棋盘上的格子是否被访问过
//深搜的时候按照这个顺序(方向)进行搜索,可以保证输出一定是字典序最小的
char dx[9] = { 0, -2, -2, -1, -1, 1, 1, 2, 2 };
char dy[9] = { 0, -1, 1, -2, 2, -2, 2, -1, 1 };
//保存最终周游路线,是总步数的两倍,最后一位留给'\0'
//由于要求字典序最小输出,并且所有格子必须要经过一遍
//因此第一个访问的必定是格子A1
char path[ 1 + ( MAXSTP << 1 ) ] = "A1";
bool
dfs( int x, int y ) {//按照dx、dy的顺序进行深搜
int i, j;//计数变量
int xx, yy;//x、y表示当前位置,xx、yy表示下一个位置
for ( i = 1; i < 9; i++ ) {
xx = x + dx[i];
yy = y + dy[i];
if ( xx < 1 || xx > r || yy < 1 || yy > c || vis[xx][yy] )
continue;
stp++;//下一位置合法,所以先试探性走一步
vis[xx][yy] = true;
j = stp << 1;//将该位置的坐标记录到路径当中
path[j - 2] = xx + 'A' - 1;
path[j - 1] = yy + '0';
//如果步数刚好达到格子的总数则表示找到周游路线成功退出即可
if ( stp == r * c ) return true;
//否则就代表还没走完所有格子,所以需要继续深搜
if ( dfs( xx, yy ) ) return true;
vis[xx][yy] = false;//如果行不通则需要将刚刚走的一步收回,试探其它走法
stp--;//步数也需要重新收回
}
return false;//所有走法都试过了还不行
}
int
main() {
int t, iscn;
int i;//技术变量
scanf("%d", &t);
iscn = 0;
while ( t-- ) {
scanf("%d%d", &c, &r);//程序中字母表示行数字表示列
printf("Scenario #%d:\n", ++iscn);
if ( 1 == r && 1 == c ) {//特殊情况
puts("A1\n");
continue;
}
if ( r > 8 || c > 8 || r < 3 || c < 3 ) {//棋盘本身限制
puts("impossible\n");
continue;
}
//进行深搜
memset(vis, false, sizeof(vis));
stp = 1;
vis[1][1] = true;
if ( !dfs( 1, 1 ) ) {
puts("impossible\n");
continue;
}
path[stp << 1] = '\0';
printf("%s\n\n", path);//输出测例之间空一行
}
return 0;
}
无注释代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#define MAXW 8
#define MAXSTP 26
int r, c;
int stp;
bool vis[MAXW][MAXW];
char dx[9] = { 0, -2, -2, -1, -1, 1, 1, 2, 2 };
char dy[9] = { 0, -1, 1, -2, 2, -2, 2, -1, 1 };
char path[ 1 + ( MAXSTP << 1 ) ] = "A1";
bool
dfs( int x, int y ) {
int i, j;
int xx, yy;
for ( i = 1; i < 9; i++ ) {
xx = x + dx[i];
yy = y + dy[i];
if ( xx < 1 || xx > r || yy < 1 || yy > c || vis[xx][yy] )
continue;
stp++;
vis[xx][yy] = true;
j = stp << 1;
path[j - 2] = xx + 'A' - 1;
path[j - 1] = yy + '0';
if ( stp == r * c ) return true;
if ( dfs( xx, yy ) ) return true;
vis[xx][yy] = false;
stp--;
}
return false;
}
int
main() {
int t, iscn;
int i;
scanf("%d", &t);
iscn = 0;
while ( t-- ) {
scanf("%d%d", &c, &r);
printf("Scenario #%d:\n", ++iscn);
if ( 1 == r && 1 == c ) {
puts("A1\n");
continue;
}
if ( r > 8 || c > 8 || r < 3 || c < 3 ) {
puts("impossible\n");
continue;
}
memset(vis, false, sizeof(vis));
stp = 1;
vis[1][1] = true;
if ( !dfs( 1, 1 ) ) {
puts("impossible\n");
continue;
}
path[stp << 1] = '\0';
printf("%s\n\n", path);
}
return 0;
}