原题:http://poj.org/problem?id=2488
题意是选择从任意位置开始以象棋中马的走法遍历,如能够遍历到所有的点则,输出路径;
理解:
(1)按照dfs进行深搜,如果按照跳马的规则无路可走而棋盘还没有全部遍历完时,则要撤销这一步,让这一步重新标记为未被访问的状态;
(2)当有多条路径可以遍历完时,按照字典的顺序输出字母最小的那条路,这时应该考虑到A1这个点,无论怎样的路径遍历完整个棋盘时都要经过A1这个点,所以我们从这个点开始搜索;
注:假设骑士起始位置在途中D4处,搜索的顺序如图1~8。
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int dx[8]={-1,1,-2,2,-2,2,-1,1};
const int dy[8]={-2,-2,-1,-1,1,1,2,2};//x表示数字的坐标,y表示字母的坐标
#define Max 30
struct way
{
int x;
char y;
}step[Max];
int t,p,q;
bool flag,vis[Max][Max];
void dfs(int x,int y,int cnt)
{
vis[x][y]=false;
step[cnt].x=x;
step[cnt].y=y+'A'-1;
if(cnt==p*q)//遍历完成
{
flag=true;
return ;
}
for(int i=0;i<8;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(nx>0&&nx<=p&&ny>0&&ny<=q&&!flag&&vis[nx][ny])
{
dfs(nx,ny,cnt+1);
vis[nx][ny]=true;//不能遍历完,这一步标记未被访问
}
}
}
int main()
{
scanf("%d",&t);
for(int c=1;c<=t;c++)
{
flag=false;
scanf("%d%d",&p,&q);
memset(vis,true,sizeof(vis));
dfs(1,1,1);
printf("Scenario #%d:\n",c);
if(flag)
{
for(int i=1;i<=p*q;i++)
{
printf("%c%d",step[i].y,step[i].x);
}
printf("\n");
}
else
printf("impossible\n");
if(c!=t)
printf("\n");
}
return 0;
}