Knight Probability in Chessboard
题目描述:在NxN的棋盘上,骑士走“日”字,经过K次行走之后,骑士还留在棋盘上的概率是多少?
骑士在棋盘上行走时,每次都有8个方向可选,走K次之后的路径树目 8K 8 K ,而假设留在棋盘上的路径数目为x,那么总共的概率为 x/8k x / 8 k 。现在问题就是如何求解x。
设矩阵F[K,R,C]表示骑士在以坐标(R,C)为起点,经过K步行走之后留在棋盘上的概率。以(R,C)为起点,8个方向分别为 (R-2,C-1),(R-1,C-2),(R+1,C-2)…(R-2,C+1),走每种方向的概率为 18 1 8 ;
所以得出如下递推公式:
F[K,R,C]=18(F[K−1,R−2,C−1]+F[K−1,R−1,C−2]+...+F[K−1,R−2,C+1])
F
[
K
,
R
,
C
]
=
1
8
(
F
[
K
−
1
,
R
−
2
,
C
−
1
]
+
F
[
K
−
1
,
R
−
1
,
C
−
2
]
+
.
.
.
+
F
[
K
−
1
,
R
−
2
,
C
+
1
]
)
F[0,R,C]=1,若R,C∈[0,N)
F
[
0
,
R
,
C
]
=
1
,
若
R
,
C
∈
[
0
,
N
)
F[K,R,C]=0,若中R,C∉[0,N)
F
[
K
,
R
,
C
]
=
0
,
若
中
R
,
C
∉
[
0
,
N
)
最终代码如下:
class Solution {
public:
double knightProbability(int N, int K, int r, int c) {
if (K == 0)
return 1;
// 假设矩阵 F[r,c,K]表示N行N列的矩阵,以(r,c)为起点的骑士,走K步后留在棋盘上的走法
vector<vector<double> > mat(N, vector<double>(N, 0.0));
vector<vector<vector<double> > > F(K+1, mat);
vector<int> row_change = { -2,-1,+1,+2,+2,+1,-1,-2 };
vector<int> col_change = { -1,-2,-2,-1,+1,+2,+2,+1 };
const int dir_count = 8;
// 初始化走1步和走0步时骑士在棋盘上的走法
for (int r = 0; r<N; ++r)
for (int c = 0; c<N; ++c)
{
F[0][r][c] = 1;
}
for (int step = 1; step <= K; ++step)
{
for (int c = 0; c < N; ++c)
{
for (int r = 0; r < N; ++r)
{
double tmp = 0;
for (int k = 0; k != dir_count; ++k)
{
int row = r + row_change[k];
int col = c + col_change[k];
if (getPath(N, row, col))
tmp += F[step - 1][row][col];
}
F[step][r][c] = tmp / dir_count;
}
}
}
return F[K][r][c];
}
// 判断骑士在r和c位置上是否可以
int getPath(const int N, const int r, const int c)
{
if (r >= 0 && r<N&&c >= 0 && c<N)
return 1;
else
return 0;
}
};