POJ 2488 A Knight's Journey (DFS)

A Knight's Journey
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u


Background
The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey 
around the world. Whenever a knight moves, it is two squares in one direction and one square perpendicular to this. The world of a knight is the chessboard he is living on. Our knight lives on a chessboard that has a smaller area than a regular 8 * 8 board, but it is still rectangular. Can you help this adventurous knight to make travel plans? 

Problem
Find a path such that the knight visits every square once. The knight can start and end on any square of the board.



Input

The input begins with a positive integer n in the first line. The following lines contain n test cases. Each test case consists of a single line with two positive integers p and q, such that 1 <= p * q <= 26. This represents a p * q chessboard, where p describes how many different square numbers 1, . . . , p exist, q describes how many different square letters exist. These are the first q letters of the Latin alphabet: A, . . .

Output

The output for every scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1. Then print a single line containing the lexicographically first path that visits all squares of the chessboard with knight moves followed by an empty line. The path should be given on a single line by concatenating the names of the visited squares. Each square name consists of a capital letter followed by a number. 
If no such path exist, you should output impossible on a single line.

Sample Input

3
1 1
2 3
4 3


Sample Output

Scenario #1:
A1

Scenario #2:
impossible

Scenario #3:
A1B3C1A2B4C2A3B1C3A4B2C4


该题说的大概意思就是,一个棋盘,然后一个棋子,该棋子只能走日字形,就和象棋中的马一样的走法,看看能不能走完棋盘中的所有的坐标,因此,不用多说,就是BFS,但是,走完所有的坐标的方法有很多种路径,这道题的结果是需要字典序的规律,这就有点难办了,该怎么处理结果呢? 难道每次搜索完以后进行一个判断?看看结果是不是字典序?这无疑变得复杂了好多,那么,到底如何为好呢? 其实在搜素中对于结果为字典序,其实只需要你搜索的时候按照字典序搜索,那么最终的结果就是字典序的!所以,你只需要规定一下先后的搜素顺序就 OK 了。这样子,第一次搜索到的结果就是你所要的结果!在该题中我是按照从上到下,从左到右的顺序,这个顺序不是随意定的,是需要按照你是把行作为A - Z还是 把列作为A - Z来区分的,这里我是把列作为A-Z字母表示的了,如果反之那么对应的搜索顺序也要修改


附上 代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <string>

using namespace std;

int n,m;
int visit[30][30];
int dt[8][2] = {-2,-1,-2,1,-1,-2,-1,2,1,-2,1,2,2,-1,2,1};  //  先后顺序的安排,按照字典序规则,也就是从上到下从左到右 

int flag;
int path[30][2];   //   path 数组记录路径,path[i][0]  表示第 i+1步的 X 坐标, path[i][1]表示第i+1步的 Y 坐标

void print(int N)
{
	for(int i = 0;i < N;i++)
	{
		printf("%c%d",path[i][0] - 1 + 'A',path[i][1]);
	}
	cout << endl;
}
void dfs(int x,int y,int N)
{
	if(flag)       //  如果搜素到了结果,那么就直接返回,不再搜索
		return;
	if(N == n * m)
	{
		flag = 1;
		print(N);
		return;
	}
	else
	{
		for(int i = 0;i < 8;i++)   //   按照安排的搜索顺序搜素
		{
			int tx = x + dt[i][0];
			int ty = y + dt[i][1];
			if(tx >= 1 && tx <= m && ty >= 1 && ty <= n && !visit[tx][ty])
			{
				visit[tx][ty] = 1;
				path[N][0] = tx;   //  记录坐标
				path[N][1] = ty;   //  记录坐标
				dfs(tx,ty,N+1);
				visit[tx][ty] = 0;
			}
		}
	}
}
int main()
{
	int t;
	cin >> t;
	int sum = 0;
	while(t--)
	{
		memset(visit,0,sizeof(visit));
		memset(path,0,sizeof(path));
		flag = 0;
		cin >> n >> m;
		visit[1][1] = 1; //  标记第一个点
		path[0][0] = 1;  //  记录第一步的坐标 X
		path[0][1] = 1;  //  记录第一步的坐标 Y
		if(sum++ > 0)
		cout << endl;
		printf("Scenario #%d:\n",sum);
		dfs(1,1,1);         //  初始点从 (1,1) 开始
		if(!flag)
		cout << "impossible" << endl;
	}
	return 0;
}


你可能感兴趣的:(ACM,poj,bfs)