##题目
688. “马”在棋盘上的概率
##内容
已知一个 NxN 的国际象棋棋盘,棋盘的行号和列号都是从 0 开始。即最左上角的格子记为 (0, 0),最右下角的记为 (N-1, N-1)。
现有一个 “马”(也译作 “骑士”)位于 (r, c) ,并打算进行 K 次移动。
如下图所示,国际象棋的 “马” 每一步先沿水平或垂直方向移动 2 个格子,然后向与之相垂直的方向再移动 1 个格子,共有 8 个可选的位置。
现在 “马” 每一步都从可选的位置(包括棋盘外部的)中独立随机地选择一个进行移动,直到移动了 K 次或跳到了棋盘外面。
求移动结束后,“马” 仍留在棋盘上的概率。
示例:
输入: 3, 2, 0, 0
输出: 0.0625
解释:
输入的数据依次为 N, K, r, c
第 1 步时,有且只有 2 种走法令 “马” 可以留在棋盘上(跳到(1,2)或(2,1))。对于以上的两种情况,各自在第2步均有且只有2种走法令 “马” 仍然留在棋盘上。
所以 “马” 在结束后仍在棋盘上的概率为 0.0625。
注意:
N 的取值范围为 [1, 25]
K 的取值范围为 [0, 100]
开始时,“马” 总是位于棋盘上
##题解
dfs搜索 定一个三层dp 通过递归 记录第k次到达当前位置时之后会留在棋牌的走法
最后输出 dp[r][c][k]
##代码
/**
* @desc
* @Description Created by chenjian on 2019/9/6.
*/
class lc688 {
double[][][] dp;
int[][] dist = {{2, 1}, {-2, 1}, {2, -1}, {-2, -1},
{1, 2}, {1, -2}, {-1, 2}, {-1, -2}};
public double knightProbability(int N, int K, int r, int c) {
if (K == 0) {
return 1;
}
dp = new double[N][N][K + 1];
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
for (int l = 0; l <= K; l++)
dp[i][j][l] = -1;
dfs(r, c, K, N, 0);
return dp[r][c][K] / Math.pow(8, K);
}
private double dfs(int r, int c, int k, int n, int count) {
if (k - count == -1) {
if (judge(r, c, n)) {
return 1;
}
return 0;
}
if (dp[r][c][k - count] == -1) {
double sum = 0;
for (int i = 0; i < 8; i++) {
if (judge(r + dist[i][0], c + dist[i][1], n)) {
sum += dfs(r + dist[i][0], c + dist[i][1], k, n, count + 1);
}
}
dp[r][c][k - count] = sum;
}
return dp[r][c][k - count];
}
private boolean judge(int r, int c, int n) {
return r >= 0 && c >= 0 && r < n && c < n;
}
}
##t提交结果