问题138 国际象棋跳跃问题 | 豆包MarsCode AI刷题

83 阅读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。

你需要在每次询问中计算从起点到终点所需的最少步数。

思路

首先,观察到总是可以在不超过3步从任意起点到达终点。

因为,想象分别以(x1,y1),(x2,y2)为中心点划出“象”可以走的斜线,两者必然有交点(x3,y3)。 如果(x3,y3)正好是整数,则可以(x1,y1) ->(x3,y3)-> (x2,y2) 不超过两步到达终点。 如果(x3,y3)为整数,代数显示这当且仅当 (x1-x2) + (y1-y2)是一个奇数,则可以通过马随便跳一步后,使得上式成为偶数,从而不超过三步到达终点。

所以,仅需要考虑3步以下的情况。

进一步发现,如move1,move2, move3 从(x1,y1) 到达(x2,y2), 那这些move的任何次序(例:move2, move1, move3)同样可以到达。

所以,可以穷举出:

  • 0步到达情况:起点等于终点
  • 1步到达情况:马, 象
  • 2步到达的情况:马马,马象,象象

根据以上的情况分类讨论即可

代码示例
#include <bits/stdc++.h>
#include <iostream>
using namespace std;

bool on_same_line(int x1, int y1, int x2, int y2) {
     return abs(x1-x2) == abs(y1 - y2);
}

bool is_same_point(int x1, int y1, int x2, int y2) {
    return x1 == x2 && y1 == y2;
}

bool on_bended_line(int x1, int y1, int x2, int y2) {
    return (x1+y1-x2-y2)%2 == 0;
}

int solution(int x1, int y1, int x2, int y2) {
    if (is_same_point(x1,y1,x2,y2)) {
        return 0;
    }
    if(on_same_line(x1,y1,x2,y2)) {
        return 1;
    }
    vector<pair<int,int>> moves;
    for(int i=-1;i<2;i+=2) {
        for(int j=-1;j<2;j+=2) {
            moves.push_back({i,2*j});
            moves.push_back({2*i,j});
        }
    }
    for(auto m: moves) {
        int x3 = x1 + m.first;
        int y3 = y1 + m.second;
        if(is_same_point(x3,y3,x2,y2)) {
            return 1;
        }
    }

    if(on_bended_line(x1,y1,x2,y2)) {
        return 2;
    }
    for(auto m: moves) {
        int x3 = x1 + m.first;
        int y3 = y1 + m.second;
        if(on_same_line(x3,y3,x2,y2)) {
            return 2;
        }
        for(auto m: moves) {
            int x4 = x3 + m.first;
            int y4 = y3 + m.second;
            if(is_same_point(x4,y4,x2,y2)) {
                return 2;
            }
        }
    }
    return 3;
}