POJ 2488 A Knight's Journey

【题号】POJ 2488

【题目描述】

A Knight's Journey

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 30404

Accepted: 10411

Description

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

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

Input

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

Output

Theoutput for every scenario begins with a line containing "Scenario#i:", where i is the number of the scenario starting at 1. Then print asingle line containing the lexicographically first path that visits all squaresof the chessboard with knight moves followed by an empty line. The path shouldbe 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

 

【类型】

DFS,注意字典序输出

【分析】

DFS进行遍历就好,记录走过的路径,只要不重复地走过p*q个方格就行了(结束条件)。

这里注意几个问题:

1、 国际象棋,横着是字母,竖着是数字。

 


根据题目的意思,比如输入4和3,可以抽象为模型:


 

2、  是按字典序输出的,所以搜索方向上一定要注意!这里是个坑。

如何确定方向数组以使得能够以字典序大小输出,这里就看你的字母在横行还是竖行了,如果是在横行就是:intdir[8][2] = {{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}};竖行就是:int dir[8][2]={-2,-1,-2,1,-1,-2,-1,2,1,-2,1,2,2,-1,2,1};我这里是在横行,总之,一个原则:要保证有字母的那一侧,严格按着字典序搜索,小的在前面,大的在后,然后数字的话就从小到大排一下。


 

所以这里方向数组应该是:int dir[8][2] = {{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}};

 

3、忽略“The knight can start and end on any square of the board.”这句话,这也算是个坑,实际上只要从A1点开始搜索就可以了,只要能从A1开始能搜到一条遍历全棋盘的路径,那么肯定从棋盘上的任意一个点作为起点都能搜出一条遍历棋盘的路径,并且题目要求要按字典序输出,所以只需从起点开始搜索就可以了!


【源代码】

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int Max = 30; 
int kase;
int p,q;
int vis[Max][Max]; //标记数组 
//方向数组,按照字典序就好了 
 int dir[8][2] = {{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}};//8个方向 
int path[Max*Max][2]; //用于记录DFS走过的路径
int flag; 

void dfs(int x, int y, int step)
{
	
	if(step == p*q) //走完了p*q格 
	{
		cout<<"Scenario #"<<++kase<<":"<<endl;
		for(int i=0; i<p*q; i++)
		{
			printf("%c%d",path[i][1]+'A',path[i][0]+1); //注意我们记录的路径下标都是从0开始的,按我这里的设计,先输出y值 
		}
		cout<<endl<<endl;
		flag = 1;
		return;
	}
		
	
	for(int d=0; d<8; d++)
	{
		int nx,ny; //只能做局部变量 
		nx = x + dir[d][0];
		ny = y + dir[d][1];
		if(!vis[nx][ny] && nx >= 0 && nx < p && ny >= 0 && ny < q) 
		{
			vis[nx][ny] = 1;
			path[step][0] = nx;
			path[step][1] = ny;
			dfs(nx, ny, step+1);
			vis[nx][ny] = 0; //取消标记
			if(flag)
				return; 
		}
	}
}

			
int main()
{
	int t;
	while(scanf("%d",&t) != EOF)
	{
		kase = 0;
		while(t--)
		{
			flag = 0;
			memset(vis, 0, sizeof(vis));
			scanf("%d %d",&p,&q);
			path[0][0] = 0;
			path[0][1] = 0;
			vis[0][0] = 1; 
			dfs(0,0,1);
			
			if(!flag)
			{
				cout<<"Scenario #"<<++kase<<":"<<endl;
				cout<<"impossible"<<endl<<endl;
			}
		}
	}
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值