问题描述
小U掌握了国际象棋中“象”和“马”的跳跃能力,在一个无限大的平面直角坐标系中,她每一步可以模仿象和马的跳跃方式移动。在每次询问中,小U需要计算从初始坐标 (x1,y1)(x1,y1) 到 (x2,y2)(x2,y2) 所需的最少步数。
- 象的跳跃:可以移动到 (x+k,y+k)(x+k,y+k) 或 (x+k,y−k)(x+k,y−k),其中 kk 是任意整数。
- 马的跳跃:可以移动到 (x+a,y+b)(x+a,y+b),其中 ∣a∣+∣b∣=3∣a∣+∣b∣=3 且 1≤∣a∣,∣b∣≤21≤∣a∣,∣b∣≤2。
你需要在每次询问中计算从起点到终点所需的最少步数。
测试样例
样例1:
输入:
x1 = 0, y1 = 0, x2 = 1, y2 = 1
输出:1
样例2:
输入:
x1 = 0, y1 = 0, x2 = 2, y2 = 1
输出:1
样例3:
输入:
x1 = 0, y1 = 0, x2 = 3, y2 = 3
输出:1
样例4:
输入:
x1 = -3, y1 = -2, x2 = 2, y2 = 1
输出:2
#include <iostream>
#include <queue>
#include <set>
#include <tuple>
#include <utility>
#include <vector>
using namespace std;
int solution(int x1, int y1, int x2, int y2) {
// Knight's possible moves
vector<pair<int, int>> knight_moves = {{2, 1}, {2, -1}, {-2, 1}, {-2, -1},
{1, 2}, {1, -2}, {-1, 2}, {-1, -2}};
// Queue stores {x, y, steps}
queue<tuple<int, int, int>> q;
set<pair<int, int>> visited;
q.push({x1, y1, 0});
visited.insert({x1, y1});
while (!q.empty()) {
auto [x, y, steps] = q.front();
q.pop();
// Handle knight moves
for (auto [dx, dy] : knight_moves) {
int nx = x + dx;
int ny = y + dy;
if (nx == x2 && ny == y2) {
return steps + 1;
}
pair<int, int> next_pos = {nx, ny};
if (visited.find(next_pos) == visited.end()) {
visited.insert(next_pos);
q.push({nx, ny, steps + 1});
}
}
// Handle bishop moves
for (int k = -100; k <= 100; k++) {
// Diagonal moves: +k,+k and +k,-k
int nx1 = x + k;
int ny1 = y + k;
if (nx1 == x2 && ny1 == y2) {
return steps + 1;
}
pair<int, int> pos1 = {nx1, ny1};
if (visited.find(pos1) == visited.end()) {
visited.insert(pos1);
q.push({nx1, ny1, steps + 1});
}
int nx2 = x + k;
int ny2 = y - k;
if (nx2 == x2 && ny2 == y2) {
return steps + 1;
}
pair<int, int> pos2 = {nx2, ny2};
if (visited.find(pos2) == visited.end()) {
visited.insert(pos2);
q.push({nx2, ny2, steps + 1});
}
}
}
return -1; // Theoretically unreachable since problem guarantees a solution
}
int main() {
std::cout << (solution(0, 0, 1, 1) == 1) << std::endl;
std::cout << (solution(0, 0, 2, 1) == 1) << std::endl;
std::cout << (solution(0, 0, 3, 3) == 1) << std::endl;
std::cout << (solution(-3, -2, 2, 1) == 2) << std::endl;
}
#include <cmath>
#include <cstdlib> // For abs()
#include <iostream>
int solution(int x1, int y1, int x2, int y2) {
int dx = x2 - x1;
int dy = y2 - y1;
// Step 0: If start and end points are the same
if (dx == 0 && dy == 0) {
return 0;
}
// Step 1: Check if reachable in exactly one move
// 1a: Check for a single Bishop move
if (dx == dy || dx == -dy) {
return 1;
}
// 1b: Check for a single Knight move
int adx = abs(dx);
int ady = abs(dy);
if ((adx == 1 && ady == 2) || (adx == 2 && ady == 1)) {
return 1;
}
// Step 2: Check if reachable in exactly two moves
bool is_target_parity_even = ((dx + dy) % 2 == 0);
if (is_target_parity_even) {
return 2;
} else {
int sum_abs = abs(dx + dy);
int diff_abs = abs(dx - dy);
if (sum_abs <= 3 || diff_abs <= 3) {
return 2;
} else {
// Step 3: If parity is odd and not reachable in 1 or 2 steps.
return 3;
}
}
}
int main() {
std::cout << (solution(0, 0, 1, 1) == 1) << std::endl;
std::cout << (solution(0, 0, 2, 1) == 1) << std::endl;
std::cout << (solution(0, 0, 3, 3) == 1) << std::endl;
std::cout << (solution(-3, -2, 2, 1) == 2) << std::endl;
return 0;
}