📌  相关文章
📜  骑士达到目标的最小步骤| 2套

📅  最后修改于: 2021-09-17 06:44:49             🧑  作者: Mango

给定一个 N x N 大小的正方形棋盘,给定骑士的位置和目标的位置,任务是找出骑士到达目标位置所需的最小步数。

例子 :

Input : (2, 4) - knight's position, (6, 4) - target cell
Output : 2

Input : (4, 5) (1, 1)
Output : 3

解决上述问题的 BFS 方法已经在上一篇文章中讨论过。在这篇文章中,讨论了动态规划解决方案。

方法说明:

  • 情况1:如果目标不在骑士位置的一行或一列。
    让一个 8 x 8 单元格的棋盘。现在,假设骑士在 (3, 3) 处,目标在 (7, 8) 处。从骑士的当前位置有可能的 8 个移动,即 (2, 1), (1, 2), (4, 1), (1, 4), (5, 2), (2, 5), (5) , 4), (4, 5)。但是,在这两个移动中,只有 (5, 4) 和 (4, 5) 将朝向目标,所有其他移动都远离目标。因此,要找到最小步骤,请转到 (4, 5) 或 (5, 4)。现在,计算从 (4, 5) 和 (5, 4) 达到目标所需的最小步数。这是通过动态规划计算的。因此,这导致从 (3, 3) 到 (7, 8) 的最小步骤。
  • 情况2:如果目标沿着骑士位置的一行或一列。
    让一个 8 x 8 单元格的棋盘。现在,假设骑士在 (4, 3) 处,目标在 (4, 7) 处。可能有 8 个移动,但是朝向目标,只有 4 个移动,即 (5, 5), (3, 5), (2, 4), (6, 4)。因为,(5, 5) 等价于(3, 5),(2, 4) 等价于(6, 4)。所以,从这4点,可以换算成2点。取 (5, 5) 和 (6, 4) (这里)。现在,计算从这两个点到达目标所需的最小步数。这是通过动态规划计算的。因此,这导致从 (4, 3) 到 (4, 7) 的最小步骤。

例外:当骑士将在角落并且目标是这样的时,x 和 y 坐标与骑士的位置的差为 (1, 1),反之亦然。那么最小步骤将是 4。

动态规划方程:

下面是上述方法的实现:

C++
// C++ code for minimum steps for
// a knight to reach target position
#include 
  
using namespace std;
  
// initializing the matrix.
int dp[8][8] = { 0 };
  
int getsteps(int x, int y, 
             int tx, int ty)
{
    // if knight is on the target 
    // position return 0.
    if (x == tx && y == ty)
        return dp[0][0];
    else {
          
        // if already calculated then return
        // that value. Taking absolute difference.
        if (dp[abs(x - tx)][abs(y - ty)] != 0)
            return dp[abs(x - tx)][abs(y - ty)];
              
        else {
  
            // there will be two distinct positions
            // from the knight towards a target.
            // if the target is in same row or column
            // as of knight than there can be four
            // positions towards the target but in that
            // two would be the same and the other two
            // would be the same.
            int x1, y1, x2, y2;
              
            // (x1, y1) and (x2, y2) are two positions.
            // these can be different according to situation.
            // From position of knight, the chess board can be
            // divided into four blocks i.e.. N-E, E-S, S-W, W-N .
            if (x <= tx) {
                if (y <= ty) {
                    x1 = x + 2;
                    y1 = y + 1;
                    x2 = x + 1;
                    y2 = y + 2;
                } else {
                    x1 = x + 2;
                    y1 = y - 1;
                    x2 = x + 1;
                    y2 = y - 2;
                }
            } else {
                if (y <= ty) {
                    x1 = x - 2;
                    y1 = y + 1;
                    x2 = x - 1;
                    y2 = y + 2;
                } else {
                    x1 = x - 2;
                    y1 = y - 1;
                    x2 = x - 1;
                    y2 = y - 2;
                }
            }
              
            // ans will be, 1 + minimum of steps 
            // required from (x1, y1) and (x2, y2).
            dp[abs(x - tx)][abs(y - ty)] = 
                           min(getsteps(x1, y1, tx, ty), 
                           getsteps(x2, y2, tx, ty)) + 1;
                             
            // exchanging the coordinates x with y of both
            // knight and target will result in same ans.
            dp[abs(y - ty)][abs(x - tx)] = 
                           dp[abs(x - tx)][abs(y - ty)];
            return dp[abs(x - tx)][abs(y - ty)];
        }
    }
}
  
// Driver Code
int main()
{
    int i, n, x, y, tx, ty, ans;
      
    // size of chess board n*n
    n = 100;
      
    // (x, y) coordinate of the knight.
    // (tx, ty) coordinate of the target position.
    x = 4;
    y = 5;
    tx = 1;
    ty = 1;
  
    // (Exception) these are the four corner points 
    // for which the minimum steps is 4.
    if ((x == 1 && y == 1 && tx == 2 && ty == 2) || 
        (x == 2 && y == 2 && tx == 1 && ty == 1))
            ans = 4;
    else if ((x == 1 && y == n && tx == 2 && ty == n - 1) ||
             (x == 2 && y == n - 1 && tx == 1 && ty == n))
                ans = 4;
    else if ((x == n && y == 1 && tx == n - 1 && ty == 2) || 
             (x == n - 1 && y == 2 && tx == n && ty == 1))
                ans = 4;
    else if ((x == n && y == n && tx == n - 1 && ty == n - 1) || 
             (x == n - 1 && y == n - 1 && tx == n && ty == n))
                ans = 4;
    else {
        // dp[a][b], here a, b is the difference of
        // x & tx and y & ty respectively.
        dp[1][0] = 3;
        dp[0][1] = 3;
        dp[1][1] = 2;
        dp[2][0] = 2;
        dp[0][2] = 2;
        dp[2][1] = 1;
        dp[1][2] = 1;
  
        ans = getsteps(x, y, tx, ty);
    }
  
    cout << ans << endl;
  
    return 0;
}


Java
//Java code for minimum steps for 
// a knight to reach target position 
public class GFG {
  
// initializing the matrix. 
    static int dp[][] = new int[8][8];
  
    static int getsteps(int x, int y,
            int tx, int ty) {
        // if knight is on the target 
        // position return 0. 
        if (x == tx && y == ty) {
            return dp[0][0];
        } else // if already calculated then return 
        // that value. Taking absolute difference. 
        if (dp[ Math.abs(x - tx)][ Math.abs(y - ty)] != 0) {
            return dp[ Math.abs(x - tx)][ Math.abs(y - ty)];
        } else {
  
            // there will be two distinct positions 
            // from the knight towards a target. 
            // if the target is in same row or column 
            // as of knight than there can be four 
            // positions towards the target but in that 
            // two would be the same and the other two 
            // would be the same. 
            int x1, y1, x2, y2;
  
            // (x1, y1) and (x2, y2) are two positions. 
            // these can be different according to situation. 
            // From position of knight, the chess board can be 
            // divided into four blocks i.e.. N-E, E-S, S-W, W-N . 
            if (x <= tx) {
                if (y <= ty) {
                    x1 = x + 2;
                    y1 = y + 1;
                    x2 = x + 1;
                    y2 = y + 2;
                } else {
                    x1 = x + 2;
                    y1 = y - 1;
                    x2 = x + 1;
                    y2 = y - 2;
                }
            } else if (y <= ty) {
                x1 = x - 2;
                y1 = y + 1;
                x2 = x - 1;
                y2 = y + 2;
            } else {
                x1 = x - 2;
                y1 = y - 1;
                x2 = x - 1;
                y2 = y - 2;
            }
  
            // ans will be, 1 + minimum of steps 
            // required from (x1, y1) and (x2, y2). 
            dp[ Math.abs(x - tx)][ Math.abs(y - ty)]
                    = Math.min(getsteps(x1, y1, tx, ty),
                            getsteps(x2, y2, tx, ty)) + 1;
  
            // exchanging the coordinates x with y of both 
            // knight and target will result in same ans. 
            dp[ Math.abs(y - ty)][ Math.abs(x - tx)]
                    = dp[ Math.abs(x - tx)][ Math.abs(y - ty)];
            return dp[ Math.abs(x - tx)][ Math.abs(y - ty)];
        }
    }
  
// Driver Code 
    static public void main(String[] args) {
        int i, n, x, y, tx, ty, ans;
  
        // size of chess board n*n 
        n = 100;
  
        // (x, y) coordinate of the knight. 
        // (tx, ty) coordinate of the target position. 
        x = 4;
        y = 5;
        tx = 1;
        ty = 1;
  
        // (Exception) these are the four corner points 
        // for which the minimum steps is 4. 
        if ((x == 1 && y == 1 && tx == 2 && ty == 2)
                || (x == 2 && y == 2 && tx == 1 && ty == 1)) {
            ans = 4;
        } else if ((x == 1 && y == n && tx == 2 && ty == n - 1)
                || (x == 2 && y == n - 1 && tx == 1 && ty == n)) {
            ans = 4;
        } else if ((x == n && y == 1 && tx == n - 1 && ty == 2)
                || (x == n - 1 && y == 2 && tx == n && ty == 1)) {
            ans = 4;
        } else if ((x == n && y == n && tx == n - 1 && ty == n - 1)
                || (x == n - 1 && y == n - 1 && tx == n && ty == n)) {
            ans = 4;
        } else {
            // dp[a][b], here a, b is the difference of 
            // x & tx and y & ty respectively. 
            dp[1][0] = 3;
            dp[0][1] = 3;
            dp[1][1] = 2;
            dp[2][0] = 2;
            dp[0][2] = 2;
            dp[2][1] = 1;
            dp[1][2] = 1;
  
            ans = getsteps(x, y, tx, ty);
        }
  
        System.out.println(ans);
    }
}
  
/*This code is contributed by PrinciRaj1992*/


Python3
# Python3 code for minimum steps for
# a knight to reach target position
  
# initializing the matrix.
dp = [[0 for i in range(8)] for j in range(8)];
  
  
def getsteps(x, y, tx, ty):
      
    # if knight is on the target
    # position return 0.
    if (x == tx and y == ty):
        return dp[0][0];
      
    # if already calculated then return
    # that value. Taking absolute difference.
    elif(dp[abs(x - tx)][abs(y - ty)] != 0):
        return dp[abs(x - tx)][abs(y - ty)];
    else:
  
        # there will be two distinct positions
        # from the knight towards a target.
        # if the target is in same row or column
        # as of knight than there can be four
        # positions towards the target but in that
        # two would be the same and the other two
        # would be the same.
        x1, y1, x2, y2 = 0, 0, 0, 0;
  
        # (x1, y1) and (x2, y2) are two positions.
        # these can be different according to situation.
        # From position of knight, the chess board can be
        # divided into four blocks i.e.. N-E, E-S, S-W, W-N .
        if (x <= tx):
            if (y <= ty):
                x1 = x + 2;
                y1 = y + 1;
                x2 = x + 1;
                y2 = y + 2;
            else:
                x1 = x + 2;
                y1 = y - 1;
                x2 = x + 1;
                y2 = y - 2;
  
        elif (y <= ty):
            x1 = x - 2;
            y1 = y + 1;
            x2 = x - 1;
            y2 = y + 2;
        else:
            x1 = x - 2;
            y1 = y - 1;
            x2 = x - 1;
            y2 = y - 2;
  
        # ans will be, 1 + minimum of steps
        # required from (x1, y1) and (x2, y2).
        dp[abs(x - tx)][abs(y - ty)] = \
        min(getsteps(x1, y1, tx, ty), 
        getsteps(x2, y2, tx, ty)) + 1;
  
        # exchanging the coordinates x with y of both
        # knight and target will result in same ans.
        dp[abs(y - ty)][abs(x - tx)] = \
        dp[abs(x - tx)][abs(y - ty)];
        return dp[abs(x - tx)][abs(y - ty)];
  
# Driver Code
if __name__ == '__main__':
  
    # size of chess board n*n
    n = 100;
  
    # (x, y) coordinate of the knight.
    # (tx, ty) coordinate of the target position.
    x = 4;
    y = 5;
    tx = 1;
    ty = 1;
  
    # (Exception) these are the four corner points
    # for which the minimum steps is 4.
    if ((x == 1 and y == 1 and tx == 2 and ty == 2) or
            (x == 2 and y == 2 and tx == 1 and ty == 1)):
        ans = 4;
    elif ((x == 1 and y == n and tx == 2 and ty == n - 1) or
        (x == 2 and y == n - 1 and tx == 1 and ty == n)):
        ans = 4;
    elif ((x == n and y == 1 and tx == n - 1 and ty == 2) or
        (x == n - 1 and y == 2 and tx == n and ty == 1)):
        ans = 4;
    elif ((x == n and y == n and tx == n - 1 and ty == n - 1)
        or (x == n - 1 and y == n - 1 and tx == n and ty == n)):
        ans = 4;
    else:
  
        # dp[a][b], here a, b is the difference of
        # x & tx and y & ty respectively.
        dp[1][0] = 3;
        dp[0][1] = 3;
        dp[1][1] = 2;
        dp[2][0] = 2;
        dp[0][2] = 2;
        dp[2][1] = 1;
        dp[1][2] = 1;
  
        ans = getsteps(x, y, tx, ty);
  
    print(ans);
  
# This code is contributed by PrinciRaj1992


C#
// C# code for minimum steps for 
// a knight to reach target position 
  
using System;
public class GFG{
  
  
// initializing the matrix. 
    static int [ , ]dp = new int[8 , 8]; 
  
    static int getsteps(int x, int y, 
            int tx, int ty) { 
        // if knight is on the target 
        // position return 0. 
        if (x == tx && y == ty) { 
            return dp[0 , 0]; 
        } else // if already calculated then return 
        // that value. Taking  Absolute difference. 
        if (dp[ Math. Abs(x - tx) , Math. Abs(y - ty)] != 0) { 
            return dp[ Math. Abs(x - tx) , Math. Abs(y - ty)]; 
        } else { 
  
            // there will be two distinct positions 
            // from the knight towards a target. 
            // if the target is in same row or column 
            // as of knight than there can be four 
            // positions towards the target but in that 
            // two would be the same and the other two 
            // would be the same. 
            int x1, y1, x2, y2; 
  
            // (x1, y1) and (x2, y2) are two positions. 
            // these can be different according to situation. 
            // From position of knight, the chess board can be 
            // divided into four blocks i.e.. N-E, E-S, S-W, W-N . 
            if (x <= tx) { 
                if (y <= ty) { 
                    x1 = x + 2; 
                    y1 = y + 1; 
                    x2 = x + 1; 
                    y2 = y + 2; 
                } else { 
                    x1 = x + 2; 
                    y1 = y - 1; 
                    x2 = x + 1; 
                    y2 = y - 2; 
                } 
            } else if (y <= ty) { 
                x1 = x - 2; 
                y1 = y + 1; 
                x2 = x - 1; 
                y2 = y + 2; 
            } else { 
                x1 = x - 2; 
                y1 = y - 1; 
                x2 = x - 1; 
                y2 = y - 2; 
            } 
  
            // ans will be, 1 + minimum of steps 
            // required from (x1, y1) and (x2, y2). 
            dp[ Math. Abs(x - tx) , Math. Abs(y - ty)] 
                    = Math.Min(getsteps(x1, y1, tx, ty), 
                            getsteps(x2, y2, tx, ty)) + 1; 
  
            // exchanging the coordinates x with y of both 
            // knight and target will result in same ans. 
            dp[ Math. Abs(y - ty) , Math. Abs(x - tx)] 
                    = dp[ Math. Abs(x - tx) , Math. Abs(y - ty)]; 
            return dp[ Math. Abs(x - tx) , Math. Abs(y - ty)]; 
        } 
    } 
  
// Driver Code 
    static public void Main() { 
        int i, n, x, y, tx, ty, ans; 
  
        // size of chess board n*n 
        n = 100; 
  
        // (x, y) coordinate of the knight. 
        // (tx, ty) coordinate of the target position. 
        x = 4; 
        y = 5; 
        tx = 1; 
        ty = 1; 
  
        // (Exception) these are the four corner points 
        // for which the minimum steps is 4. 
        if ((x == 1 && y == 1 && tx == 2 && ty == 2) 
                || (x == 2 && y == 2 && tx == 1 && ty == 1)) { 
            ans = 4; 
        } else if ((x == 1 && y == n && tx == 2 && ty == n - 1) 
                || (x == 2 && y == n - 1 && tx == 1 && ty == n)) { 
            ans = 4; 
        } else if ((x == n && y == 1 && tx == n - 1 && ty == 2) 
                || (x == n - 1 && y == 2 && tx == n && ty == 1)) { 
            ans = 4; 
        } else if ((x == n && y == n && tx == n - 1 && ty == n - 1) 
                || (x == n - 1 && y == n - 1 && tx == n && ty == n)) { 
            ans = 4; 
        } else { 
            // dp[a , b], here a, b is the difference of 
            // x & tx and y & ty respectively. 
            dp[1 , 0] = 3; 
            dp[0 , 1] = 3; 
            dp[1 , 1] = 2; 
            dp[2 , 0] = 2; 
            dp[0 , 2] = 2; 
            dp[2 , 1] = 1; 
            dp[1 , 2] = 1; 
  
            ans = getsteps(x, y, tx, ty); 
        } 
  
        Console.WriteLine(ans); 
    } 
} 
  
/*This code is contributed by PrinciRaj1992*/


输出:
3

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程