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

原创 2016年05月30日 09:51:31
 题目描述:
    在国际象棋的棋盘上放置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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

HDOJ.1342 Lotto (DFS)

Lotto点我挑战题目题意分析给出k(6 < k < 13)个数字,要求从这k个数字中选出升序的6个数字,并且按照字典序输出全部的可能,给出的k个数字已经按照升序排列好。 乍一看以为是排列组合,怎么...

ACM:搜索算法专题(4)——数独

题目来源:         HihoCoder1321   题目描述:     给定一个数独方阵,通过程序给出数独的解。 解答: ·数独:    ...

hdu--1342 lotto (dfs)

#include "stdio.h"#include "string.h"#include "math.h"int visit[14],save[6],a[14];int n,cur;void DFS...

HDU 1342 Lotto 【DFS】

Lotto Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su...

The Heaviest Non-decreasing Subsequence Problem 最长非递减子序列 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛

题目链接根据题意,把值变换成数的个数,这样就变成了求最长非递减子序列,这里用O(n*log(n))的办法#include using namespace std; typedef long long ...

广度优先、深度优先搜索算法——LeetCode

广度优先搜索(Breadth-first Search)、深度优先搜索(Depth-first Search)算法面试题——LeetCode

ACM:搜索算法专题(3)——启发式搜索

题目来源:          HihoCoder1312 题目描述:     给出一个九宫格的拼图游戏的棋局,求完成拼图最少需要一定的步数。 解答: ·规则:...

Frequent Subsets Problem 进制运算 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛

题目链接因为n只到20,直接利用二进制的位运算暴力解决,1代表有该元素,0代表没有该元素#include using namespace std; typedef long long ll; int ...

ACM:搜索算法专题(1)——24点

题目描述:     给定4个数字,判定这4个数字是否可以通过运算得到结果24。运算操作包括:加、减、乘、除,允许变换数字的顺序,允许使用括号改变运算顺序。     即:判定是否存在一种通过在下面的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)