给定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)