A Knight's Jounery 骑士旅行 北大poj2488 深度优先搜索相关 计算机考研机试指南整理

题目链接:A Knight’s Jounery

题目大意:

骑士按照“日”字规则行走,找一条能够让骑士遍历棋盘上所有点的路径,骑士可以在任何一块方块上开始和结束。要求在所有可行的路径中输出字母表排序最小的那个解。

样例输入:

第一行为样例个数,其余每一行为棋盘大小。

3
1 1
2 3
4 3

样例输出:

Scenario #1:
A1

Scenario #2:
impossible

Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4

分析

并不是求最优解,而是判定是否存在一条符合条件的路径,所以使用深度优先搜索来达到这个目的。
搜索状态三元组(x,y,step)。目标状态(x,y,step),其中step = x*y。因为是按照日字型形状走,所以当前状态可以扩展出八个状态,当然,这些状态要按照字典序的顺序来安排。
宽度优先搜索使用队列实现先进先出,深度优先搜索使用递归来实现早得到的状态后得到扩展。

A Knight's Jounery 骑士旅行 北大poj2488 深度优先搜索相关 计算机考研机试指南整理_第1张图片

#include 
#include 
#include 
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}
}; //这里的状态分布式按照字典序的规则走的,比如A2 
 
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;
		if(!DFS(0,0,1,"A1")){
			cout<<"impossible"<<endl<<endl;
		}
	}
	
} 

深度优先搜索,从一个状态一直访问其子状态,当符合条件后,就输出。若子状态不符合条件,转而判断上一层。

你可能感兴趣的:(算法刷题,算法)