leetcode 688. “马”在棋盘上的概率

题目描述:

已知一个 NxN 的国际象棋棋盘,棋盘的行号和列号都是从 0 开始。即最左上角的格子记为 (0, 0),最右下角的记为 (N-1, N-1)。 

现有一个 “马”(也译作 “骑士”)位于 (r, c) ,并打算进行 K 次移动。 

如下图所示,国际象棋的 “马” 每一步先沿水平或垂直方向移动 2 个格子,然后向与之相垂直的方向再移动 1 个格子,共有 8 个可选的位置。

思路分析:

思路1: 首先想到的是用dfs,但是这样会超时,最坏情况可能达到8的100次方。

思路2: 三维dp,dp[i][j][k]表示在点(i, j)上移动了k次后改点仍然位于棋盘上的概率。首先,初始条件dp[i][j][0]=1。接下来四层的循环,最外层为1到k次的移动,接下来是位置i,j的两重循环,最后是移动方向1到8的循环,dp[i][j][num] = sum(dp[i][j][num-1]*(1.0/8.0)),即当前点k次的概率为所有k-1次的概率之和。

代码:

 1 class Solution {
 2 public:
 3     double knightProbability(int N, int K, int r, int c) {
 4         if(K<=0)
 5             return 1.0;
 6         if(N<0 || r<0 || r>=N || c<0 || c>=N)
 7             return 0.0;
 8         double dp[26][26][101];
 9         int direction[][2] = {{-1, -2}, {1, -2}, {-1, 2}, {1, 2}, {-2, -1}, {-2, 1}, {2, -1}, {2, 1}};
10         for(int i=0; i<N; i++)
11             for(int j=0; j<N; j++)
12                 dp[i][j][0]=1;
13         for(int num=1; num<=K; num++)
14         {
15             for(int i=0; i<N; i++)
16             {
17                 for(int j=0; j<N; j++)
18                 {
19                     double tmp = 0;
20                     for(int l=0; l<8; l++)
21                     {
22                         int x = i+direction[l][0];
23                         int y = j+direction[l][1];
24                         if(x<0 || y<0 || x>=N || y>=N)
25                             continue;
26                         tmp += (1.0/8.0)*dp[x][y][num-1];
27                     }
28                     dp[i][j][num] = tmp;
29                 }
30             }
31         }
32         return dp[r][c][K];
33     }
34 };
原文地址:https://www.cnblogs.com/LJ-LJ/p/11323361.html