题目大意:
给定一个p*q的棋盘(p行q列或者q行p列都行,我是理解为q行p列),一个Knight在该棋盘上行走(走日字),可以从棋盘的任意方格出发,要求不重复的走完所有的方格,输出字典序最小的行走路线。q行:A、B、C...,p列:1、2、3...p;题目连接:http://poj.org/problem?id=2488
解题思路:
一道经典的“骑士游历问题”,网上说是DFS水题,可我觉得还是有些难度。毕竟DFS学的不好。
由于题目要求是按照字典序输出行走路线,那么在深搜的时候对扩展节点的搜索顺序是有要求的,搜索顺序如下所示:
代码:
#include<iostream>
#include<fstream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<sstream>
#include<cassert>
using namespace std;
#define LL __int64
int p,q;
int vis[30][30];
int dx[]={-2,-2,-1,-1,1,1,2,2}; //搜索顺序有特殊要求
int dy[]={-1,1,-2,2,-2,2,-1,1};
int th=0;
int step[30][2]; //记录行走的路线
bool dfs(int x,int y,int num){
if(num==p*q){ //走完所有的方格
step[th][0]=x;
step[th++][1]=y+1;
return true;
}
vis[x][y]=1;
for(int i=0;i<8;i++){
int tmpx,tmpy;
tmpx=x+dx[i];
tmpy=y+dy[i];
if(tmpx>=0 && tmpx<q && tmpy>=0 && tmpy<p && !vis[tmpx][tmpy]){
if(dfs(tmpx,tmpy,num+1)){
step[th][0]=x;step[th++][1]=y+1;
return true;
}
}
}
vis[x][y]=0;
return false;
}
int main(){
int n;
scanf("%d",&n);
for(int k=1;k<=n;k++){
scanf("%d%d",&p,&q);
memset(vis,0,sizeof(vis));
int flag=0;
for(int i=0;i<q;i++){
for(int j=0;j<p;j++){
th=0;
if(dfs(i,j,1)){
flag=1;
break;
}
}
if(flag)
break;
}
printf("Scenario #%d:\n",k);
if(!flag){
printf("impossible\n");
}
else{
for(int i=th-1;i>=0;i--){
printf("%c%d",step[i][0]+'A',step[i][1]);
}
printf("\n");
}
if(k<n)
printf("\n");
}
return 0;
}