青训营X豆包MarsCode 技术训练营国际象棋跳跃问题 | 豆包MarsCode AI 刷题

212 阅读4分钟

国际象棋跳跃问题

1.问题描述

小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。

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

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

3.题目思路

解题思路是通过检查象和马的移动规则来确定从起点到终点所需的最少步数。首先,它检查是否可以通过象的一步对角线移动直接到达终点,或者马的一步L形移动直接到达终点。如果这两种直接移动都不可行,它再检查曼哈顿距离的奇偶性,如果曼哈顿距离是偶数,则至少需要两步(象的移动),如果是奇数,则检查是否可以通过马的移动调整奇偶性,如果可以,则需要两步,如果不可以,则需要三步。

4.详细方法
定义马的移动:

首先定义两个数组 stepx 和 stepy,它们包含了马的所有可能移动。马可以移动到的位置是 (x+a,y+b)(x+a,y+b),其中 ∣a∣+∣b∣=3∣a∣+∣b∣=3 且 1≤∣a∣,∣b∣≤21≤∣a∣,∣b∣≤2。数组 stepx 和 stepy 分别存储了马在x和y方向上的移动。

检查象的移动:

函数首先检查终点是否可以通过象的移动直接到达。如果 ∣x2−x1∣=∣y2−y1∣∣x2​−x1​∣=∣y2​−y1​∣,这意味着两点在对角线上的距离相等,因此可以通过象的一步移动到达。在这种情况下,函数返回1。

检查马的移动:

如果终点不能通过象的移动直接到达,函数接下来检查是否可以通过马的移动直接到达。它遍历马的所有可能移动,并检查是否有任何移动可以使终点与起点对齐。如果找到这样的移动,函数返回1。

检查偶数和奇数的曼哈顿距离:

如果终点既不能通过象的移动也不能通过马的移动直接到达,函数检查曼哈顿距离 ∣x2−x1∣+∣y2−y1∣∣x2​−x1​∣+∣y2​−y1​∣ 是否为偶数。如果为偶数,这意味着可以通过两次象的移动到达终点(每次移动覆盖一半的距离),所以函数返回2。

检查通过马调整的象移动:

如果曼哈顿距离是奇数,函数检查是否可以通过添加马的移动来调整奇偶性。它遍历马的所有可能移动,并检查是否有任何移动可以使调整后的终点与起点在对角线上的距离相等。如果找到这样的移动,函数返回2。

返回:

如果上述所有条件都不满足,函数返回3,这意味着需要三步才能到达终点。

5.代码实现
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include <functional>
using namespace std;
typedef long long ll;
 
int stepx[8]={-1,1,2,2,1,-1,-2,-2};
int stepy[8]={2,2,1,-1,-2,-2,-1,1};
 
int solution(int x1, int y1, int x2, int y2) {
    // write code here
    int i=0,j=0,tx=0,ty=0;
    //The first condition
    if(abs(x2-x1)==abs(y2-y1)){
        return 1;
    }
    //The second condition
    for(i=0;i<8;i++){
        if(x1+stepx[i]==x2 && y1+stepy[i]==y2){
            return 1;
        }
    }
    //The third condition
    if((abs(x2-x1)+abs(y2-y1))%2==0){
        return 2;
    }
    //The forth condition
    else{
        for(i=0;i<8;i++){
            tx=x2+stepx[i];
            ty=y2+stepy[i];
            if(abs(tx-x1)==abs(ty-y1)){
                return 2;
            }
        }
        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;
}