前言
在深度优先搜索中,对搜索的状态而言,获得一个状态后,同样立即扩展这个状态,但需要保证早得到的状态较后得到扩展,即先入后出特性,可使用栈或递归。
由于深度优先搜索并没有先入先出的特点,所以搜索到需要的状态时,该状态不再具有BFS那样的某种最优的特性。因此,使用DFS常常是为了知道问题是否有解,而不使用DFS求解最优解问题。
题目
骑士按照“日”字规则行走。骑士的世界就是他生活的8*8棋盘
找到一条能够让骑士遍历棋盘上所有点的路径。骑士可以在任何一块方块上开始或结束他的旅行。
思路
搜索状态三元组(x,y,step),(x,y)是当前点的坐标,step是从起点走到该点经过的步数。需要搜索到的最终目标状态为(x,y,step),其中step=p*q,即经过的步数等于棋盘的格数。需要记录棋盘中的某点骑士是否曾经访问过,防止重复经过同一点。
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int MAXN=30;
int p,q;//棋盘参数
bool visit[MAXN][MAXN];//标记矩阵
int direction[8][2]={
{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}
};
bool DFS(int x,int y,int step,string ans){
if(step==p*q)
{
cout<<ans<<endl<<endl;
return true;
}
else{
for(int i=0;i<8;i++)//遍历邻居结点
{
int nx=x+direction[i][0];//扩展状态坐标
int ny=y+direction[i][1];
char col = ny +'A';//该点编号
char row = nx + '1';
if(nx<0||nx>=p||ny<0||ny>=q||visit[nx][ny])
continue;
visit[nx][ny]=true;//标记该点
if(DFS(nx,ny,step+1,ans+col+row))
return true;
visit[nx][ny]=false;//取消标记
}
}
return false;
}
int main()
{
int n;
cin>>n;
int caseNumber = 0;
while(n--)
{
cin>>p>>q;
memset(visit,false,sizeof(visit));
cout<<"Scenario #"<<++caseNumber<<":"<<endl;
visit[0][0]=true; //标记A1点
if(!DFS(0,0,1,"A1"))
cout<<"impossible"<<endl<<endl;
}
return 0;
}