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

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

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

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

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

现在 “马” 每一步都从可选的位置(包括棋盘外部的)中独立随机地选择一个进行移动,直到移动了 K 次或跳到了棋盘外面。

求移动结束后,“马” 仍留在棋盘上的概率。

输入: 3, 2, 0, 0
输出: 0.0625

思路

①每次有8个方向可以走,走到K为0的时候例子剩下4种走法在棋盘上,所以P=4/8²=0.0625.只需记录走到最后在棋盘上的个数即可。超时代码。

class Solution {
public:
    int move[8][2] = { { 1, 2 }, { 1, -2 }, { 2, 1 }, { 2, -1 }, { -1, 2 }, { -1, -2 }, { -2, 1 }, { -2, -1 } };
    int count=0;
    double knightProbability(int N, int K, int r, int c) {
        dfs(N,K,r,c);
        return count*1.0/pow(8,K);
    }
    void dfs(int N, int K, int r, int c){
        if(!(r>=0 && r<N && c>=0 && c<N)) return ;//跳出棋盘的不算
        if(K==0){count++; return ;}//最后一步在棋盘上
        for(int i=0;i<8;i++){
            dfs(N, K-1, r+move[i][0], c+move[i][1]);
        } 
    }
};

②用dp[r][c][k]记录在r,c位置,还剩K次的结果(棋盘内的概率)

class Solution {
public:
    int move[8][2] = { { 1, 2 }, { 1, -2 }, { 2, 1 }, { 2, -1 }, { -1, 2 }, { -1, -2 }, { -2, 1 }, { -2, -1 } };
    double dp[25][25][101];//dp[r][c][k],记录在rc位置上还有k步的概率。
    double knightProbability(int N, int K, int r, int c) {
        fill(dp[0][0],dp[0][0]+25*25*101,0);
        return dfs(N,K,r,c);;
    }
    double dfs(int N, int K, int r, int c){
        if(K==0) return 1;
        if(dp[r][c][K]!=0) return dp[r][c][K];
        double res=0;//记录8次中的概率总和
        for(int i=0;i<8;i++){
            int r1 = r+move[i][0];
            int c1 = c+move[i][1];
            if(r1 >= 0 && r1 < N && c1 >= 0 && c1 < N){//在棋盘内
                res += dfs(N,K-1,r1,c1);
            }
        }
        return dp[r][c][K]=res/8;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值