您的位置:首页 > 其它

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

程序代码:

/****************************************************/
/* 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: