ACM:搜索算法专题(2)——骑士问题
2016-05-30 09:51
435 查看
题目描述:
在国际象棋的棋盘上放置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
程序代码:
在国际象棋的棋盘上放置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; }
相关文章推荐
- 【MySQL】
- 05.30
- linux sleep usleep
- 命令:netstat 常用操作记录
- Linux命令行编辑快捷键
- Dev GridControl控件属性设置(一)
- MVC模式浅谈
- 特征描述子(-)—HOG具体实现过程
- IOS 数据库篇5—SQLite模糊查询
- ajax验证用户唯一性
- 背水一战 Windows 10 (15) - 动画: 缓动动画
- SharePoint 修改完或制作完一定要发布
- Resharper 8.2 注册码
- leetcode #60 in cpp
- spring Bean的五种scope
- android开发之AsyncTask的用法
- arm-linux-androideabi-addr2line
- github初识1
- Amabri 2.1 安装HDP2.3.2 之 四、安装ambari
- JS控制弹出悬浮窗口(一览画面)的实例代码