Knight Probability in Chessboard

Knight Probability in Chessboard

题目描述:在NxN的棋盘上,骑士走“日”字,经过K次行走之后,骑士还留在棋盘上的概率是多少?

骑士在棋盘上行走时,每次都有8个方向可选,走K次之后的路径树目 8 K ,而假设留在棋盘上的路径数目为x,那么总共的概率为 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),走每种方向的概率为 1 8 ;

所以得出如下递推公式:

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 [ 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;
    }
};

猜你喜欢

转载自blog.csdn.net/t46414704152abc/article/details/81098988