📜  骑士留在棋盘上的概率

📅  最后修改于: 2021-09-17 07:29:23             🧑  作者: Mango

给定一个 NxN 棋盘和一个位于 (x,y) 位置的骑士。骑士必须准确地走 K 步,在每一步,它随机均匀地选择 8 个方向中的任何一个。骑士走K步后留在棋盘上的概率是多少,条件是离开后不能再进入棋盘?
例子:

Let's take:
8x8 chessboard,
initial position of the knight : (0, 0),
number of steps : 1
At each step, the Knight has 8 different positions to choose from. 

If it starts from (0, 0), after taking one step it will lie inside the
board only at 2 out of 8 positions, and will lie outside at other positions.
So, the probability is 2/8 = 0.25

方法:

我们可以观察到的一件事是,骑士的每一步都有 8 个选择可供选择。假设,骑士必须走 k 步,在第 K 步之后,骑士到达 (x,y)。骑士一步到(x,y)有8个不同的位置,它们是:(x+1,y+2), (x+2,y+1), (x+2, y-1), (x+1,y-2), (x-1,y-2), (x-2,y-1), (x-2,y+1), (x-1, y+2)。
如果我们已经知道在 K-1 步骤后到达这 8 个位置的概率怎么办?

那么,K 步后的最终概率将简单地等于 (Σ 在 K-1 步后到达这 8 个位置中的每一个的概率)/8;

这里我们除以 8,因为这 8 个位置中的每一个都有 8 个选择,而位置 (x,y) 是选择之一。

对于位于板外的位置,我们要么将其概率视为 0,要么干脆忽略它。

由于我们需要跟踪每一步的每个位置的概率,我们需要动态规划来解决这个问题。
我们将采用一个数组 dp[x][y][steps] ,它将存储在移动(步)数后到达(x,y)的概率。

基本情况:如果步数为 0,则骑士留在棋盘内的概率为 1。
下面是上述方法的实现:

C++
// C++ program to find the probability of the
// Knight to remain inside the chessboard after
// taking exactly K number of steps
#include 
using namespace std;
 
// size of the chessboard
#define N 8
 
// direction vector for the Knight
int dx[] = { 1, 2, 2, 1, -1, -2, -2, -1 };
int dy[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
 
// returns true if the knight is inside the chessboard
bool inside(int x, int y)
{
    return (x >= 0 and x < N and y >= 0 and y < N);
}
 
// Bottom up approach for finding the probability to
// go out of chessboard.
double findProb(int start_x, int start_y, int steps)
{
    // dp array
    double dp1[N][N][steps + 1];
 
    // for 0 number of steps, each position
    // will have probability 1
    for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j)
            dp1[i][j][0] = 1;
 
    // for every number of steps s
    for (int s = 1; s <= steps; ++s) {
         
        // for every position (x,y) after
        // s number of steps
        for (int x = 0; x < N; ++x) {
            for (int y = 0; y < N; ++y) {
                double prob = 0.0;
 
                // for every position reachable from (x,y)
                for (int i = 0; i < 8; ++i) {
                    int nx = x + dx[i];
                    int ny = y + dy[i];
 
                    // if this position lie inside the board
                    if (inside(nx, ny))
                        prob += dp1[nx][ny][s - 1] / 8.0;
                }
 
                // store the result
                dp1[x][y][s] = prob;
            }
        }
    }
 
    // return the result
    return dp1[start_x][start_y][steps];
}
 
// Driver Code
int main()
{
    // number of steps
    int K = 3;
 
    // Function Call
    cout << findProb(0, 0, K) << endl;
 
    return 0;
}


Java
// Java program to find the probability
// of the Knight to remain inside the
// chessboard after taking exactly K
// number of steps
class GFG {
 
    // size of the chessboard
    static final int N = 8;
 
    // direction vector for the Knight
    static int dx[] = { 1, 2, 2, 1, -1, -2, -2, -1 };
 
    static int dy[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
 
    // returns true if the knight is
    // inside the chessboard
    static boolean inside(int x, int y)
    {
        return (x >= 0 && x < N && y >= 0 && y < N);
    }
 
    // Bottom up approach for finding
    // the probability to go out of
    // chessboard.
    static double findProb(int start_x, int start_y,
                           int steps)
    {
 
        // dp array
        double dp1[][][] = new double[N][N][steps + 1];
 
        // for 0 number of steps, each position
        // will have probability 1
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < N; ++j)
                dp1[i][j][0] = 1;
 
        // for every number of steps s
        for (int s = 1; s <= steps; ++s) {
 
            // for every position (x, y) after
            // s number of steps
            for (int x = 0; x < N; ++x) {
 
                for (int y = 0; y < N; ++y) {
 
                    double prob = 0.0;
 
                    // for every position reachable
                    // from (x, y)
                    for (int i = 0; i < 8; ++i) {
                        int nx = x + dx[i];
                        int ny = y + dy[i];
 
                        // if this position lie
                        // inside the board
                        if (inside(nx, ny))
                            prob
                                += dp1[nx][ny][s - 1] / 8.0;
                    }
 
                    // store the result
                    dp1[x][y][s] = prob;
                }
            }
        }
 
        // return the result
        return dp1[start_x][start_y][steps];
    }
 
    // Driver code
    public static void main(String[] args)
    {
 
        // number of steps
        int K = 3;
 
        // Function Call
        System.out.println(findProb(0, 0, K));
    }
}
 
// This code is contributed by Anant Agarwal.


Python3
# Python3 program to find the probability of
# the Knight to remain inside the chessboard
# after taking exactly K number of steps
# size of the chessboard
N = 8
 
# Direction vector for the Knight
dx = [1, 2, 2, 1, -1, -2, -2, -1]
dy = [2, 1, -1, -2, -2, -1, 1, 2]
 
# returns true if the knight
# is inside the chessboard
 
def inside(x, y):
    return (x >= 0 and x < N and y >= 0 and y < N)
 
# Bottom up approach for finding the
# probability to go out of chessboard.
 
def findProb(start_x, start_y, steps):
 
    # dp array
    dp1 = [[[0 for i in range(N+5)]
            for j in range(N+5)]
            for k in range(steps + 5)]
 
    # For 0 number of steps, each
    # position will have probability 1
    for i in range(N):
        for j in range(N):
            dp1[i][j][0] = 1
 
    # for every number of steps s
    for s in range(1, steps + 1):
 
        # for every position (x,y) after
        # s number of steps
        for x in range(N):
 
            for y in range(N):
                prob = 0.0
 
                # For every position reachable from (x,y)
                for i in range(8):
                    nx = x + dx[i]
                    ny = y + dy[i]
 
                    # if this position lie inside the board
                    if (inside(nx, ny)):
                        prob += dp1[nx][ny][s-1] / 8.0
 
                # store the result
                dp1[x][y][s] = prob
 
    # return the result
    return dp1[start_x][start_y][steps]
 
# Driver code
 
# number of steps
K = 3
 
# Function Call
print(findProb(0, 0, K))
 
# This code is contributed by Anant Agarwal.


C#
// C# program to find the
// probability of the Knight
// to remain inside the
// chessboard after taking
// exactly K number of steps
using System;
 
class GFG {
 
    // size of the chessboard
    static int N = 8;
 
    // direction vector
    // for the Knight
    static int[] dx = { 1, 2, 2, 1, -1, -2, -2, -1 };
 
    static int[] dy = { 2, 1, -1, -2, -2, -1, 1, 2 };
 
    // returns true if the
    // knight is inside the
    // chessboard
    static bool inside(int x, int y)
    {
        return (x >= 0 && x < N && y >= 0 && y < N);
    }
 
    // Bottom up approach for
    // finding the probability
    // to go out of chessboard.
    static double findProb(int start_x, int start_y,
                           int steps)
    {
 
        // dp array
        double[, , ] dp1 = new double[N, N, steps+1];
 
        // for 0 number of steps,
        // each position will have
        // probability 1
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < N; ++j)
                dp1[i, j, 0] = 1;
 
        // for every number
        // of steps s
        for (int s = 1; s <= steps; ++s) {
 
            // for every position (x, y)
            // after s number of steps
            for (int x = 0; x < N; ++x) {
                for (int y = 0; y < N; ++y) {
                    double prob = 0.0;
 
                    // for every position
                    // reachable from (x, y)
                    for (int i = 0; i < 8; ++i) {
                        int nx = x + dx[i];
                        int ny = y + dy[i];
 
                        // if this position lie
                        // inside the board
                        if (inside(nx, ny))
                            prob
                                += dp1[nx, ny, s - 1] / 8.0;
                    }
 
                    // store the result
                    dp1[x, y, s] = prob;
                }
            }
        }
 
        // return the result
        return dp1[start_x, start_y, steps];
    }
 
    // Driver code
    static void Main()
    {
        // number of steps
        int K = 3;
 
        // Function Call
        Console.WriteLine(findProb(0, 0, K));
    }
}
 
// This code is contributed
// by Sam007


PHP
= 0 and $x < $N and
            $y >= 0 and $y < $N);
}
 
// Bottom up approach for finding the
// probability to go out of chessboard.
function findProb($start_x, $start_y, $steps)
{
    global $N, $dx, $dy;
     
    // dp array
    $dp1 = array_fill(0, $N,
           array_fill(0, $N,
           array_fill(0, $steps+1, NULL)));
 
    // for 0 number of steps, each
    // position will have probability 1
    for ($i = 0; $i < $N; ++$i)
        for ($j = 0; $j < $N; ++$j)
            $dp1[$i][$j][0] = 1;
 
    // for every number of steps s
    for ($s = 1; $s <= $steps; ++$s)
    {
        // for every position (x,y) after
        // s number of steps
        for ($x = 0; $x < $N; ++$x)
        {
            for ($y = 0; $y < $N; ++$y)
            {
                $prob = 0.0;
 
                // for every position
                // reachable from (x,y)
                for ($i = 0; $i < 8; ++$i)
                {
                    $nx = $x + $dx[$i];
                    $ny = $y + $dy[$i];
 
                    // if this position lie inside
                    // the board
                    if (inside($nx, $ny))
                        $prob += $dp1[$nx][$ny][$s - 1] / 8.0;
                }
 
                // store the result
                $dp1[$x][$y][$s] = $prob;
            }
        }
    }
 
    // return the result
    return $dp1[$start_x][$start_y][$steps];
}
 
// Driver Code
 
// number of steps
$K = 3;
 
// Function Call
echo findProb(0, 0, $K) . "\n";
 
// This code is contributed by ita_c
?>


Javascript


输出
0.125

时间复杂度:O(NxNxKx8) 即 O(NxNxK),其中 N 是电路板的大小,K 是步数。
空间复杂度:O(NxNxK)

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