算法课作业系列8——Knight Probability in Chessboard

来源:互联网 发布:淘宝店过户费用 编辑:程序博客网 时间:2024/05/22 10:39

算法课作业系列(8)

Knight Probability in Chessboard

写在前面

话说当年数据结构考试的时候这是最后一题,当时我在电脑前写代码写得焦头烂额,看着别人一个一个走完,哎~最后成绩也不是很理想。今天看到了这道题,正好也出现在动态规划这一类里面,因此就想着要写出来,下面开始吧!

题目

On an NxN chessboard, a knight starts at the r-th row and c-th column and attempts to make exactly K moves. The rows and columns are 0 indexed, so the top-left square is (0, 0), and the bottom-right square is (N-1, N-1).

A chess knight has 8 possible moves it can make, as illustrated below. Each move is two squares in a cardinal direction, then one square in an orthogonal direction.

这里写图片描述

Each time the knight is to move, it chooses one of eight possible moves uniformly at random (even if the piece would go off the chessboard) and moves there.

The knight continues moving until it has made exactly K moves or has moved off the chessboard. Return the probability that the knight remains on the board after it has stopped moving.

Example:
Input: 3, 2, 0, 0
Output: 0.0625
Explanation: There are two moves (to (1,2), (2,1)) that will keep the knight on the board.
From each of those positions, there are also two moves that will keep the knight on the board.
The total probability the knight stays on the board is 0.0625.

Note:
N will be between 1 and 25.
K will be between 0 and 100.
The knight always initially starts on the board.

思路

好了,不要吐槽我直接粘贴题目过来了,因为我已经尽力让你们看题目没那么困难了,题目看一遍就好,重要的在思路。上面我说过了,这道题使用的是动态规划,因此我们就应该以动态规划的思路去想。我们先随机选一个点i,j,在选一个k值来看,容易想到,在这一点的概率也就是所有八个点留在k - 1步留在棋盘上的概率和在除以8,怎么说呢,因为每个点周围的8个点都有等大的几率被选到,而每个点留在棋盘上的几率也不一样,因此我们只需要考虑周围点留在棋盘的几率乘以1/8,再加起来就可以了。我们一层一层推下去,会发现对于每个点,如果要求0步留在棋盘上,也就是什么都不做,那这里的概率一定就是1啊,因为这个点本来就在棋盘上。用数组来表示的话,假设要求i,j点k步留在棋盘上,那么只需要令
f[k][i][j] = (f[k - 1][i + 1][j + 2] + f[k - 1][i + 1][j - 2] + f[k - 1][i - 1][j + 2] + f[k - 1][i - 1][j - 2] + f[k - 1][i + 2][j - 1] + f[k - 1][i + 2][j + 1] + f[k - 1][i - 2][j - 1] + f[k - 1][i - 2][j + 1]) / 8
看起来很复杂,其实就是一句话,周围8个位置的概率和除以8,如果出界了,那就一定是0啦。

代码

class Solution {public:    double knightProbability(int N, int K, int r, int c) {        double ***dp;        dp = new double**[K + 1];        for (int k = 0; k <= K; k++) {            dp[k] = new double*[N];            for (int i = 0; i < N; i++) {                dp[k][i] = new double[N];                for (int j = 0; j < N; j++) {                    if (k == 0) {                        dp[0][i][j] = 1;                    } else {                        double sum = 0;                        if (i - 1 >= 0) {                            if (j - 2 >= 0) {                                sum += dp[k - 1][i - 1][j - 2];                            }                            if (j + 2 < N) {                                sum += dp[k - 1][i - 1][j + 2];                            }                        }                        if (i - 2 >= 0) {                            if (j - 1 >= 0) {                                sum += dp[k - 1][i - 2][j - 1];                            }                            if (j + 1 < N) {                                sum += dp[k - 1][i - 2][j + 1];                            }                        }                        if (i + 1 < N) {                            if (j - 2 >= 0) {                                sum += dp[k - 1][i + 1][j - 2];                            }                            if (j + 2 < N) {                                sum += dp[k - 1][i + 1][j + 2];                            }                        }                        if (i + 2 < N) {                            if (j - 1 >= 0) {                                sum += dp[k - 1][i + 2][j - 1];                            }                            if (j + 1 < N) {                                sum += dp[k - 1][i+ 2][j + 1];                            }                        }                        sum /= 8;                        dp[k][i][j] = sum;                    }                }            }        }        return dp[K][r][c];    }};

写在后面

代码还是要多写的,多想想,灵活运用才可以。

原创粉丝点击