POJ2488 A Knight's Journey(AC2)

A Knight's Journey
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 36713 Accepted: 12469

Description

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
 
测试数据可见http://poj.org/showmessage?message_id=162294

好的分析路径:http://blog.csdn.net/lyy289065406/article/details/6647666

花费时间:一天,还是有参考百度,自己要增加独立思考的能力 
 
注意国际象棋中行为数字,列为字母

 

 

//第二次做的

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>


//POJ2488 A Knight's Journey
#if 1
//这个顺序也是要严格按照字典序的顺序来的,要不然得到的结果就是不对的
//重新做这道题主体代码都是对的,主要就是这个顺序没弄对,还有这个
//注意马到1的位置是(-1,-2)不是(-2,-1)这个自己是严重犯了错误
//同样输出少了个\n
#define MAXINT 30

int dir[8][2] = { { -1, -2 }, { 1, -2 }, { -2, -1 }, { 2, -1 }, { -2, 1 }, { 2, 1 }, { -1, 2 }, { 1, 2 } };
char path[MAXINT][2]; //有2个长度A1就是2个长度
int visit[MAXINT][MAXINT];

int p = 0;
int q = 0;

void init()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < MAXINT;i++)
	{
		for (j = 0; j < MAXINT; j++)
		{
			visit[i][j] = 0;
		}
		path[MAXINT][0] = '\0';
		path[MAXINT][1] = '\0';
	}
	return;
}

void printfpath()
{
	int i = 0;
	for (i = 1; i <= (p*q); i++)
	{
		printf("%c%c", path[i][0], path[i][1]);
	}
	printf("\n");
	return;
}

//x负责数字,y负责字母,第1列y
char GetnameZimu(int y)
{
	return ('A' + y - 1);
}

char GetnameShuzi(int x)
{
	return ('0' + x);
}

//p是列,p负责数字,q是行,q负责字母
int dfs(int x, int y,int num)
{
	int i = 0;
	if ((x<1)||(x>p)||(y<1)||(y>q)) return 0;
	if ((p*q) == num) return 1;

	for (i = 0; i < 8;i++)
	{
		int x1 = x + dir[i][0];
		int y1 = y + dir[i][1];
		if ((x1<1) || (x1>p) || (y1<1) || (y1>q)) continue;
		if (1 == visit[x1][y1]) continue;
		visit[x1][y1] = 1;
		path[num + 1][0] = GetnameZimu(y1);
		path[num + 1][1] = GetnameShuzi(x1);
		if (1 == dfs(x1,y1,num+1))
		{
			return 1;
		}
		else
		{
			//回溯
			visit[x1][y1] = 0;
			path[num + 1][0] = '\0';
			path[num + 1][1] = '\0';
		}
	}
	return 0;
}
int main()
{
	int i = 0;
	int T = 0;
	freopen("input.txt","r",stdin);
	scanf("%d",&T);
	for (i = 0; i < T;i++)
	{
		init();
		scanf("%d %d", &p, &q);
		//可以从任何一个位置出发,那就从第一个位置出发,这个是(1,1)开始,这个是字典序中最小的
		printf("Scenario #%d:\n", i + 1);
		visit[1][1] = 1;
		path[1][0] = 'A';
		path[1][1] = '1';
		if (1 == dfs(1, 1,1))
		{
			printfpath();
		}
		else
		{
			printf("impossible\n");
		}
		printf("\n");
	}
	return 0;
}
#endif


 

 
//code pojAC
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

/*3
1 1
2 3
4 3
从题意中看4 3, 4是列,4是行
*/

/*提交记录
1:第一次提交wa, 再看了下题目加百度,发现输入p,q不是那么简单理解的,自己理解成p是列,q是行,不对的,应该是p是行,q是列
2:第二次提交提示格式错误,原来输出要隔2行,好吧。。。*/

#define MAXINT 100

typedef struct info
{
 char zimu;
 int index;
}infos;

int p        = 0;
int q       = 0;
int visitsqure = 1;
int sum = 0;
int flag = 0;

int   map[MAXINT][MAXINT];
char  zimu[MAXINT][MAXINT];
int   visit[MAXINT][MAXINT];
infos que[MAXINT*MAXINT];

//因为输出要求按照字典序,因此这个方向也是要按照字典序的方向,先拍字母,然后排数字,这个方向已定要对
int dir[8][2] = { { -1, -2 }, {1,-2}, {-2,-1}, {2,-1}, {-2,1}, {2,1}, {-1,2}, {1,2} };

int dfs(int x, int y, int step)
{
 int i = 0;
 if (x <= 0 || x > p || y<0 || y>q) return 0;
 visit[x][y] = 1; 
 que[step].zimu = zimu[x][y];
 que[step].index = map[x][y];
 if (1 == flag) return 1;

 if (step == sum)
 {
  flag = 1;
  return 1;
 }

 for (i = 0; i < 8;i++)
 {
  int x1 = x + dir[i][0];
  int y1 = y + dir[i][1];
  if (x1 <= 0 || x1 > p || y1<=0 || y1>q) continue;
  if (visit[x1][y1]) continue;
  visit[x1][y1] = 1;
  if (1 == dfs(x1, y1, step+1))
  {
   return 1;
  }
  visit[x1][y1] = 0;
 }
 return 0;
}

void init()
{
 int k = 0;
 int j = 0;
 int tmp = 1;
 
 for (j = 1; j <= p; j++)
 {
  for (k = 1; k <= q; k++)
  {
   map[j][k]   = 0;
   zimu[j][k]  = '\0';
   visit[j][k] = 0;
  }
  que[tmp].zimu    = '\0';
  que[tmp++].index = 0;
 }
 visitsqure = 1;
 sum = 0;
    flag = 0;
 return;
}
//从第一点出发
int main()
{
 int T = 0;
 int i = 0;
 int j = 0;
 int k = 0;
 int zimuindex = 65; //小a 97,大A65
 freopen("input.txt", "r", stdin);
 scanf("%d",&T);
 for (i = 0; i < T;i++)
 {
  scanf("%d %d", &p, &q);
  init();
  sum = p*q;
  zimuindex = 65;
  for (j = 1; j <= q;j++)
  {
   for (k = 1; k <= p; k++)
   {
    map[k][j]  = k;
    zimu[k][j] = zimuindex; //输入也要注意,之前自己就弄错了,输入好像还是弄错了,p是行,q是列,自己以为输入是列,行,不对,是行,列
   }
   zimuindex += 1;
  }
  //要求是按照字典序的顺序输出的
  if (1 == dfs(1, 1, 1))//从1行1列经过
  {
   printf("Scenario #%d:\n", i + 1);
   for (j = 1; j <= sum;j++)
   {
    printf("%c%d", que[j].zimu, que[j].index);
   }
   printf("\n\n");
  }
  else
  {
   printf("Scenario #%d:\n",i+1);
   printf("impossible\n\n");
  }
 }
 return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值