Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 46639 | Accepted: 15875 |
Description
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
Output
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
题目大意:给你N组数据,输入N组p,q,p代表棋盘的行数,q代表棋盘的列数。任选一个起点,按照国际象棋马的跳法,不重复的跳完整个棋盘,如果有多种路线则选择字典序最小的路线(路线是点的横纵坐标的集合,注意棋盘的横坐标的用大写字母,纵坐标是数字)
题目分析:
1. 应该看到这个题就可以想到用DFS,当首先要明白这个题的意思是能否只走一遍(不回头不重复)将整个地图走完,而普通的深度优先搜索是一直走,走不通之后沿路返回到某处继续深搜。所以这个题要用到的回溯思想,如果不重复走一遍就走完了,做一个标记,算法停止;否则在某种DFS下走到某一步时按马跳的规则无路可走而棋盘还有为走到的点,这样我们就需要撤消这一步,进而尝试其他的路线(当然其他的路线也可能导致撤销),而所谓撤销这一步就是在递归深搜返回时重置该点,以便在当前路线走一遍行不通换另一种路线时,该点的状态是未访问过的,而不是像普通的DFS当作已经访问了。
2. 如果有多种方式可以不重复走一遍的走完,需要输出按字典序最小的路径,而注意到国际象棋的棋盘是列为字母,行为数字,如果能够不回头走一遍的走完,一定会经过A1点,所以我们应该从A1开始搜索,以确保之后得到的路径字典序是最小的(也就是说如果路径不以A1开始,该路径一定不是字典序最小路径),而且我们应该确保优先选择的方向是字典序最小的方向,这样我们最先得到的路径就是字典序最小的。
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int vis[27][27];
int dir[9][2]={0,0,-1,-2,1,-2,-2,-1,2,-1,-2,1,2,1,-1,2,1,2};
int x,y;
bool flag=false;
struct node
{
int x,y;
}path[27];
bool check(int x1,int y1)
{
if(x1<1||x1>x||y1<1||y1>y||flag==true||vis[x1][y1]==1) return false;
else return true;
}
void DFS(int x0,int y0,int num)
{
int i;
path[num].x=x0,path[num].y=y0;
//printf("x0y0:%d %d %d\n",x0,y0,vis[x0][y0]);
if(num==x*y) {flag=true;return ;}
for(i=1;i<=8;i++)
{
int x1=x0+dir[i][0],y1=y0+dir[i][1];
if(check(x1,y1))
{
vis[x1][y1]=1;
DFS(x1,y1,num+1);
vis[x1][y1]=0;//回溯
}
}
}
int main()
{
int n,i;
char c;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
flag=false;
memset(vis,0,sizeof(vis));
scanf("%d %d",&x,&y);
vis[1][1]=1;
DFS(1,1,1);
if(flag==false) printf("Scenario #%d:\nimpossible\n",i);
else
{
printf("Scenario #%d:\n",i);
for(int j=1;j<=x*y;j++)
{
printf("%c%d",path[j].y+64,path[j].x);
}
printf("\n");
}
if(i!=n) printf("\n");
}
return 0;
}