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.
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.
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字母表示的了,如果反之那么对应的搜索顺序也要修改
附上 代码:
/*
* 如果搜索的时候 将总 x 作为 纵坐标,将 y 作为 横坐标,那么从一个跳到周围八个点的顺序为
* 1 2
* 3 4
* 5 6
* 7 8
* 如果搜索的时候 将总 x 作为 横坐标,将 y 作为 纵坐标,那么从一个跳到周围八个点的顺序为
* 3 5
* 1 7
* 2 8
* 4 6
* 只要顺序对了,搜索并记录路径就行了 ,因为制定了搜索的先后顺序,所以搜索的时候的第一个结果就是我们需要的
*/
#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;
}