POJ 2488 A Knight's Journey

题目大意:

        考察马能否周游一遍棋盘上所有的格子一遍(不重复经过同一个格子),有t个测例,每个测例都会给出棋盘大小p×q,其中1 ≤ pq ≤ 26,其中p表示的棋盘的行(1 ~ 8),q表示棋盘的列数(A ~ A+q-1),对于每个测例如果可以周游就输出一条周游路线,路线中先后包括一路上经过的格子的代号,比如"A1B2E4"就代表先后经过了1行A列、2行B列、4行E列,如果存在多条路线,则输出字典序最小的那条路线,如果不存在则输出"impossible"。

题目链接

注释代码:

/*                               
 * Problem ID : POJ 2488 A Knight's Journey 
 * Author     : Lirx.t.Una                               
 * Language   : C++                   
 * Run Time   : 0 ms                               
 * Run Memory : 132 KB                               
*/ 

#include <iostream>
#include <cstring>
#include <cstdio>

//棋盘最大宽度(3×9=27>26)
#define	MAXW	8
//最大周游步数25步
#define	MAXSTP	26

//程序中行为字母,列为数字
int		r, c;//棋盘的行数和列数
int		stp;//当前马做过的步数
bool	vis[MAXW][MAXW];//棋盘上的格子是否被访问过

//深搜的时候按照这个顺序(方向)进行搜索,可以保证输出一定是字典序最小的
char	dx[9] = { 0, -2, -2, -1, -1,  1, 1,  2, 2 };
char	dy[9] = { 0, -1,  1, -2,  2, -2, 2, -1, 1 };

//保存最终周游路线,是总步数的两倍,最后一位留给'\0'
//由于要求字典序最小输出,并且所有格子必须要经过一遍
//因此第一个访问的必定是格子A1
char	path[ 1 + ( MAXSTP << 1 ) ] = "A1";

bool
dfs( int x, int y ) {//按照dx、dy的顺序进行深搜

	int		i, j;//计数变量
	int		xx, yy;//x、y表示当前位置,xx、yy表示下一个位置

	for ( i = 1; i < 9; i++ ) {
	
		xx = x + dx[i];
		yy = y + dy[i];

		if ( xx < 1 || xx > r || yy < 1 || yy > c || vis[xx][yy] )
			continue;

		stp++;//下一位置合法,所以先试探性走一步
		vis[xx][yy]  = true;

		j = stp << 1;//将该位置的坐标记录到路径当中
		path[j - 2] = xx + 'A' - 1;
		path[j - 1] = yy + '0';

		//如果步数刚好达到格子的总数则表示找到周游路线成功退出即可
		if ( stp == r * c ) return true;
		//否则就代表还没走完所有格子,所以需要继续深搜
		if ( dfs( xx, yy ) ) return true;

		vis[xx][yy] = false;//如果行不通则需要将刚刚走的一步收回,试探其它走法
		stp--;//步数也需要重新收回
	}
	
	return false;//所有走法都试过了还不行
}

int
main() {

	int		t, iscn;

	int		i;//技术变量

	scanf("%d", &t);
	iscn = 0;

	while ( t-- ) {
	
		scanf("%d%d", &c, &r);//程序中字母表示行数字表示列
		printf("Scenario #%d:\n", ++iscn);

		if ( 1 == r && 1 == c ) {//特殊情况
			
			puts("A1\n");
			continue;
		}

		if ( r > 8 || c > 8 || r < 3 || c < 3 ) {//棋盘本身限制
		
			puts("impossible\n");
			continue;
		}

		//进行深搜
		memset(vis, false, sizeof(vis));

		stp = 1;
		vis[1][1] = true;
		if ( !dfs( 1, 1 ) ) {
		
			puts("impossible\n");
			continue;
		}

		path[stp << 1] = '\0';
		printf("%s\n\n", path);//输出测例之间空一行
	}

	return 0;
}
无注释代码:

#include <iostream>
#include <cstring>
#include <cstdio>

#define	MAXW	8
#define	MAXSTP	26

int		r, c;
int		stp;
bool	vis[MAXW][MAXW];

char	dx[9] = { 0, -2, -2, -1, -1,  1, 1,  2, 2 };
char	dy[9] = { 0, -1,  1, -2,  2, -2, 2, -1, 1 };

char	path[ 1 + ( MAXSTP << 1 ) ] = "A1";

bool
dfs( int x, int y ) {

	int		i, j;
	int		xx, yy;

	for ( i = 1; i < 9; i++ ) {
	
		xx = x + dx[i];
		yy = y + dy[i];

		if ( xx < 1 || xx > r || yy < 1 || yy > c || vis[xx][yy] )
			continue;

		stp++;
		vis[xx][yy]  = true;

		j = stp << 1;
		path[j - 2] = xx + 'A' - 1;
		path[j - 1] = yy + '0';

		if ( stp == r * c ) return true;
		if ( dfs( xx, yy ) ) return true;

		vis[xx][yy] = false;
		stp--;
	}
	
	return false;
}

int
main() {

	int		t, iscn;

	int		i;

	scanf("%d", &t);
	iscn = 0;

	while ( t-- ) {
	
		scanf("%d%d", &c, &r);
		printf("Scenario #%d:\n", ++iscn);

		if ( 1 == r && 1 == c ) {
			
			puts("A1\n");
			continue;
		}

		if ( r > 8 || c > 8 || r < 3 || c < 3 ) {
		
			puts("impossible\n");
			continue;
		}

		memset(vis, false, sizeof(vis));

		stp = 1;
		vis[1][1] = true;
		if ( !dfs( 1, 1 ) ) {
		
			puts("impossible\n");
			continue;
		}

		path[stp << 1] = '\0';
		printf("%s\n\n", path);
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值