关闭

ACM:搜索算法专题(2)——骑士问题

901人阅读 评论(0) 收藏 举报
分类:
 题目描述:
    在国际象棋的棋盘上放置3个骑士的棋子,按照骑士的移动规则移动这3个棋子,使其到达同一个位置,求最少的移动次数。

解答:
    本题不难。首先说明一下国际象棋的规则,棋盘由8×8=64个黑白相间的格子组成,棋子放在某一个格子中。采用二维坐标的方式表示棋盘中的每一个格子,其中水平方向从左到右用 A-H 这8个英文字母表示,竖直方向从下到上用 1-8 这8个数字表示,如下图:
     
    
    国际向其中的棋子“骑士”的走法和中国象棋中的马的走法类似,沿着一个2×3的矩形区域的对角线移动,如下图: 
     
    因此在不考虑棋盘的范围的情况下,假设棋盘的范围无限,那么每一个马都有8个不同的位置使得该棋子移动1次就可到达:
     
后续的步骤可分为两种方法进行:

·方法一: 
    将棋盘中的每一个位置和其他8个可以直接到达的位置用边连接,同时设定边的长度为1,那么分别将3个棋子的初始位置作为起点,利用dijkstra算法就可以计算出该棋子到达每个位置时需要移动的最小步数。将3个棋子的情况分别计算后,枚举棋盘中的每一个位置,找到使得3个棋子的移动到该位置的步数的总和的最小值,就是本题的答案。

·方法二:
    也可以同时对于3个棋子的位置来分析。由于每个棋子的横纵坐标都只有8种不同的可能,因此,3个棋子的位置就可以用一个6位的8进制数来表示,用不同的数字表示不同的“状态点”,由于每一个棋子都有8个位置可以移动一次到达,因此每个“状态点”都有3×8=24个不同的“状态点”,可以通过移动1此3个棋子中的某一个棋子来达到与当前状态点的转换,因此,此时抽象出的“图”中的每个“点”最多有24个“点”与其邻接。以初始位置的状态作为起点,利用dijkstra算法找到和其他所有状态的最短距离,然后遍历那些3个棋子在同一个位置的状态,找到最短的距离即可。

下面的代码采用的是方法一。


输入输出格式:
    输入:第1行:1个正整数t,表示数据组数,2≤t≤10;第2..t+1行:用空格隔开的3个坐标, 每个坐标由2个字符AB组成,A为A-H的大写字母,B为1-8的数字,表示3个棋子的初始位置。
    输出:
第1..t行:每行1个数字,第i行表示第i组数据中3个棋子移动到同一格的最小行动步数。

数据范围:
     2 ≤ t ≤ 10

程序代码:
/****************************************************/
/* File        : Hiho_Week_99                       */
/* Author      : Zhang Yufei                        */
/* Date        : 2016-05-24                         */
/* Description : HihoCoder ACM program. (submit:g++)*/
/****************************************************/

#include<stdio.h>
#include<stdlib.h>

/*
 * Define structure to record chess information.
 */
typedef struct node {
	int distance;
	int tag;
} chess;

/*
 * Record the position which is accessable by moving only once from orginal place.
 */
int position[8][2] = {
	{-1,  2}, { 1,  2}, { 2, -1}, { 2,  1},
	{-1, -2}, { 1, -2}, {-2, -1}, {-2,  1}
};

/* 
 * Record the map of chess. The element is the mininum steps to move from the
 * start position
 */
chess **chess1;
chess **chess2;
chess **chess3;

/*
 * This function computes the shortest distance between every position in the map
 * and the start position.
 * Parameters:
 *		@x & @y: The start postion.
 *		@map: The chess map.
 * Returns:
 *		None.
 */
void dijkstra(chess **map, int x, int y) {
	map[x][y].distance = 0;
	map[x][y].tag = 1;
	
	int set[64][2];
	set[0][0] = x;
	set[0][1] = y;
	
	int xi, yi, x_n, y_n;
	int min_x, min_y;
	int min; 
	
	min_x = x;
	min_y = y;
	for(int i = 0; i < 8; i++) {
		x_n = min_x + position[i][0];
		y_n = min_y + position[i][1];
		if(x_n >= 0 && x_n < 8 && y_n >= 0 && y_n < 8) {
			if(map[x_n][y_n].tag == 0) {
				if(map[x_n][y_n].distance == -1 || 
					map[x_n][y_n].distance > map[min_x][min_y].distance + 1) {
					map[x_n][y_n].distance = map[min_x][min_y].distance + 1;
				}
			}
		}	
	}
	
	int count = 1;
	while(count < 64) {
		min = -1;
		
		for(int i = 0; i < count; i++) {
			xi = set[i][0];
			yi = set[i][1];
			for(int j = 0; j < 8; j++) {
				x_n = xi + position[j][0];
				y_n = yi + position[j][1];
				if(x_n >= 0 && x_n < 8 && y_n >= 0 && y_n < 8) {
					if(map[x_n][y_n].tag == 0) {
						if(min == -1 || min > map[x_n][y_n].distance) {
							min = map[x_n][y_n].distance;
							min_x = x_n;
							min_y = y_n;
						}
					}
				}
			}
		}
		
		map[min_x][min_y].tag = 1;
		set[count][0] = min_x;
		set[count][1] = min_y;
		count++;
		
		for(int i = 0; i < 8; i++) {
			x_n = min_x + position[i][0];
			y_n = min_y + position[i][1];
			if(x_n >= 0 && x_n < 8 && y_n >= 0 && y_n < 8) {
				if(map[x_n][y_n].tag == 0) {
					if(map[x_n][y_n].distance == -1 || 
						map[x_n][y_n].distance > map[min_x][min_y].distance + 1) {
						map[x_n][y_n].distance = map[min_x][min_y].distance + 1;
					}
				}
			}	
		}
	}
}
 		
/*
 * The main program.
 */
int main(void) {
	chess1 = (chess**) malloc(sizeof(chess*) * 8);
	for(int i = 0; i < 8; i++) {
		chess1[i] = (chess*) malloc(sizeof(chess) * 8);
	}
	
	chess2 = (chess**) malloc(sizeof(chess*) * 8);
	for(int i = 0; i < 8; i++) {
		chess2[i] = (chess*) malloc(sizeof(chess) * 8);
	}
	
	chess3 = (chess**) malloc(sizeof(chess*) * 8);
	for(int i = 0; i < 8; i++) {
		chess3[i] = (chess*) malloc(sizeof(chess) * 8);
	}
	int t;
	
	scanf("%d", &t);
	
	for(; t > 0; t--) {
		for(int i = 0; i < 8; i++) {
			for(int j = 0; j < 8; j++) {
				chess1[i][j].distance = chess2[i][j].distance 
					= chess3[i][j].distance = -1;
				chess1[i][j].tag = chess2[i][j].tag 
					= chess3[i][j].tag = 0;
			}
		}
		
		char location[3];
		
		scanf("%s", location);
		dijkstra(chess1, location[0] - 'A', location[1] - '1');
		
		scanf("%s", location);
		dijkstra(chess2, location[0] - 'A', location[1] - '1');
		
		scanf("%s", location);
		dijkstra(chess3, location[0] - 'A', location[1] - '1');	
		
		int min = -1;
		
		for(int i = 0; i < 8; i++) {
			for(int j = 0; j < 8; j++) {
				int s = chess1[i][j].distance + chess2[i][j].distance 
					+ chess3[i][j].distance;
				if(min == -1 || min > s) {
					min = s;
				}
			}
		}
		
		printf("%d\n", min);	 
	}
	
	return 0;
}


1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:32391次
    • 积分:1004
    • 等级:
    • 排名:千里之外
    • 原创:68篇
    • 转载:10篇
    • 译文:0篇
    • 评论:6条
    文章分类
    最新评论