出身背景
Somurov先生是一位出色的国际象棋棋手,他断言,除了他之外,没有人能如此迅速地将骑士从一个位置移动到另一个位置。你能打败他吗?
问题
你的任务是编写一个程序来计算骑士从一个点到另一个点所需的最小移动次数,这样你就有机会比索穆罗洛夫更快。
对于不熟悉国际象棋的人来说,可能的骑士招式如图1所示。
输入 输入以单行上的场景数量n开始。 接下来是n个场景。每个场景由包含整数的三行组成。第一行指定了棋盘一侧的长度l(4<=l<=300)。整个棋盘的大小为ll。第二行和第三行包含一对整数{0,…,l-1}{0,..,l-1},指定骑士在棋盘上的起始和结束位置。整数由一个空格分隔。您可以假设这些位置是该场景中棋盘上的有效位置。 输出 对于输入的每个场景,您必须计算从起点移动到终点所需的骑士移动的最小数量。如果起点和终点相等,则距离为零。距离必须写在一行上。
Sample Input 3 8 0 0 7 0 100 0 0 30 50 10 1 1 1 1 Output 5 28 0
思路
将起点放入队列,向八个方向进行搜索。注意判断是否出界。
AC代码
#include <iostream>
#include <queue>
#include <cstring>
#define AUTHOR "HEX9CF"
using namespace std;
struct SPoint
{
int x;
int y;
int step;
};
int go[8][2] = {
{1, 2},
{2, 1},
{-1, 2},
{-2, 1},
{1, -2},
{2, -1},
{-1, -2},
{-2, -1}
};
int bfs(int l, int x1, int y1, int x2, int y2)
{
if (x1 == x2 && y1 == y2)
{
return 0;
}
bool gnd[l][l];
queue<SPoint> Q;
memset(gnd, 0, sizeof(gnd));
SPoint start, node;
start.x = x1;
start.y = y1;
start.step = 0;
Q.push(start);
while (!Q.empty())
{
int x0, y0, step;
start = Q.front();
Q.pop();
x0 = start.x;
y0 = start.y;
step = start.step;
for (int j = 0; j < 8; j++)
{
int x3, y3;
x3 = x0 + go[j][0];
y3 = y0 + go[j][1];
if (x3 == x2 && y3 == y2)
{
return step + 1;
}
if (x3 >= 0 && x3 < l && y3 >= 0 && y3 < l && !gnd[x3][y3])
{
node.x = x3;
node.y = y3;
node.step = step + 1;
Q.push(node);
gnd[x3][y3] = 1;
}
}
}
return 0;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int x1, y1, x2, y2, l;
cin >> l >> x1 >> y1 >> x2 >> y2;
cout << bfs(l, x1, y1, x2, y2) << endl;
}
return 0;
}