Leetcode 688. 骑士在棋盘上的概率【中等】

题目

https://leetcode-cn.com/problems/knight-probability-in-chessboard/

执行结果

执行用时:4 ms, 在所有 C++ 提交中击败了99.80%的用户
内存消耗:5.9 MB, 在所有 C++ 提交中击败了96.96%的用户
通过测试用例:22 / 22

解题思路

  1. 首先可以确定的是一道数学题中的概率题;
  2. 考虑只走一步的情况,因为有八种走法,所以每种走法的固定概率是1/8。判断每种走法是否在棋盘内,将在棋盘内的走法的概率相加就是结果。这一步的重点是运用概率论中的加法原则
  3. 对于走多步的情况,则是需要运用概率论中的乘法原则。举个例子,假如第i步走到格子(p,q)的概率是0.1,那么第i+1步就是从(p,q)出发再走一步看看能走到哪里,也就是步骤2的走法。如果某个走法走到了(x,y)这个格子是在棋盘内,那么这个格子的概率就是P = 0.1*(1/8)。考虑到可能有多种可能都会走到(x,y)这个格子,所以需要将这个概率P进行累加。
  4. 实现时使用两个二维数组保存状态。grid保存第i步执行完之后棋盘的状态,在第i+1步根据grid的状态更新grid_tmp。

代码

class Solution {
    const static int MAX_N{25};
    double grid[MAX_N][MAX_N];
    double grid_tmp[MAX_N][MAX_N];
    //八种走法代表的方向
    int dir[8][2]{
        {-2, -1},
        {-1, -2},
        {1, -2},
        {2, -1},
        {2, 1},
        {1, 2},
        {-1, 2},
        {-2, 1}
    };
    // 每种走法的固定概率
    double rat{1.0/8.0};
public:
    void initGrid(double pp[MAX_N][MAX_N], int n, double val)
    {
        for (int i = 0; i < n; ++i){
            for (int j = 0; j < n; ++j){
                pp[i][j] = val;
            }
        }
    }
    double knightProbability(int n, int k, int row, int column) {
        //此处将grid初始化成-1.0可以避免与浮点数0.0比较时的精度问题
        initGrid(grid, n, -1.0);
        grid[row][column] = 1.0;
        for (int i = 0; i < k; ++i){
            //将grid_tmp初始化为0.0是因为后面需要做累加
            initGrid(grid_tmp, n, 0.0);
            for (int p = 0; p < n; ++p){
                for (int q = 0; q < n; ++q){
                    if (grid[p][q] > 0.0){
                        // 此处执行步骤2
                        for (int j = 0; j < 8; ++j){
                            int x = p + dir[j][0];
                            int y = q + dir[j][1];
                            if (x >= 0 && x < n && y >= 0 && y < n){
                                //先乘后累加
                                grid_tmp[x][y] += rat * grid[p][q];
                            }
                        }
                    }
                }
            }
            // 将grid_tmp复制给grid
            for (int p = 0; p < n; ++p){
                for (int q = 0; q < n; ++q){
                    if (grid_tmp[p][q] > 0.0){
                        grid[p][q] = grid_tmp[p][q];
                    }else {
                        grid[p][q] = -1.0;
                    }
                }
            }
        }
        double sum{0.0};
        for (int i = 0; i < n; ++i){
            for (int j = 0; j < n; ++j){
                if (grid[i][j] > 0.0){
                    sum += grid[i][j];
                }
            }
        }
        return sum;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

superbin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值