hiho_99_骑士问题
题目大意
给定国际象棋8x8棋盘上三个起始点,三个骑士分别从三个起始点开始移动(骑士只能走日字,且骑士从任意一点出发可以走遍整个棋盘)。现要求三个骑士汇聚到棋盘上某个点,且使得骑士到达该点所移动的次数总和最小。求该最小移动次数。
题目连接:骑士问题
题目分析
典型的搜索,最短路径可以使用BFS。骑士数只有三个,因此可以求出每个骑士到达棋盘上所有点的移动的次数,再遍历一遍棋盘,求出最小次数和。
实现
#pragma once #pragma execution_character_set("utf-8") // 本文件为utf-8 编码格式 #include<iostream> #include<string.h> #include<stdio.h> #include<unordered_map> #include<unordered_set> #include<string> #include<stack> #include<queue> using namespace std; struct Node{ int x, y, step; Node(int xx, int yy, int s) :x(xx), y(yy), step(s){}; }; int move_step[9][9][3]; bool visited[9][9]; int move_inc[8][2] = { { -2, -1 }, { -2, 1 }, { -1, 2 }, { 1, 2 }, { 2, 1 }, { 2, -1 }, { 1, -2 }, { -1, -2 } }; void Bfs(int start_x, int start_y, int knight){ memset(visited, false, sizeof(visited)); queue<Node> Q; Node node(start_x, start_y, 0); Q.push(node); visited[start_x][start_y] = true; while (!Q.empty()){ node = Q.front(); Q.pop(); move_step[node.x][node.y][knight] = node.step; for (int i = 0; i < 8; i++){ int next_x = node.x + move_inc[i][0]; int next_y = node.y + move_inc[i][1]; if (next_x >= 1 && next_x <= 8 && next_y >= 1 && next_y <= 8 && !visited[next_x][next_y]){ visited[next_x][next_y] = true; Q.push(Node(next_x, next_y, node.step + 1)); } } } } void Init(){ memset(move_step, -1, sizeof(move_step)); } int MinStep(){ int min = 1 << 30; for (int r = 1; r <= 8; r++){ for (int c = 1; c <= 8; c++){ min = min < (move_step[r][c][0] + move_step[r][c][1] + move_step[r][c][2]) ? min : (move_step[r][c][0] + move_step[r][c][1] + move_step[r][c][2]); } } return min; } int main(){ int T; char row, col; scanf("%d", &T); int start_x[3]; int start_y[3]; while (T--){ for (int i = 0; i < 3; i++){ getchar(); scanf("%c%c", &row, &col); start_x[i] = row - 'A' + 1; start_y[i] = col - '0'; } for (int i = 0; i < 3; i++){ Bfs(start_x[i], start_y[i], i); } int result = MinStep(); printf("%d\n", result); } return 0; }