bluecode-国际象棋跳跃问题

53 阅读2分钟

问题描述

小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;
}