您的位置:首页 > 其它

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

2017-11-04 19:31 453 查看

算法课作业系列(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*
;
for (int i = 0; i < N; i++) {
dp[k][i] = new double
;
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];
}
};


写在后面

代码还是要多写的,多想想,灵活运用才可以。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: