http://poj.org/problem?id=2488
大致题意:给出一个p行q列的国际棋盘,马可以从任意一个格子开始走,问马能否不重复的走完所有的棋盘。如果可以,输出按字典序排列最小的路径。打印路径时,列用大写字母表示(A表示第一列),行用阿拉伯数字表示(从1开始),先输出列,再输出行。
分析:如果马可以不重复的走完所有的棋盘,那么它一定可以走到A1这个格子。所以我们只需从A1这个格子开始搜索,就能保证字典序是小的;除了这个条件,我们还要控制好马每次移动的方向,控制方向时保证字典序最小(即按照下图中格子的序号搜索)。控制好这两个条件,直接从A1开始深搜就行了。
#include <iostream>
#include <deque>
#include <cstring>
using namespace std;
int dir[8][2]={-1,-2,1,-2,-2,-1,2,-1,-2,1,2,1,-1,2,1,2}; //注意顺序
int vis[8][8];
int r,c;
bool Judge(int x,int y)
{
if(vis[x][y]==0&&x>=0&&x<r&&y>=0&&y<c)
return true;
return false;
}
struct Node
{
int x,y;
};
deque<Node> d;
void Print()
{
Node t;
cout<<"A1";
while(!d.empty())
{
t=d.front();
cout<<(char)(t.y+65)<<t.x+1;
d.pop_front();
}
cout<<endl;
}
bool dfs(int x,int y)
{
int i,j,tag=0;
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
if(vis[i][j]!=1) tag=1;
if(tag==1) break;
}
if(tag==0) return true; //递归终止条件,表明所有全部访问过
for(i=0;i<8;i++)
{
int row=x+dir[i][0],col=y+dir[i][1];
if(Judge(row,col))
{
vis[row][col]=1; //设为访问过
if(dfs(row,col))
{
Node t;
t.x=row;t.y=col;
d.push_front(t); //如果DFS成功,从终点倒退到起点,故应每次应插到队首
return true;
}
else
{
vis[row][col]=0; //DFS失败,重新设置成未访问
d.clear(); //一旦DFS失败,就清空,而不是弹出一个队列元素
}
}
}
return false; //路径搜索失败
}
int main()
{
int n,i;
cin>>n;
for(i=0;i<n;i++)
{
cin>>r>>c;
vis[0][0]=1;
cout<<"Scenario #"<<i+1<<":"<<endl;
if(r==1&&c==1) cout<<"A1"<<endl;
else if(dfs(0,0)==false)
cout<<"impossible"<<endl;
else Print();
memset(vis,0,sizeof(vis));
d.clear();
if(i!=n-1)
cout<<endl;
}
return 0;
}