美文网首页
688. 马在棋盘上的概率(Python)

688. 马在棋盘上的概率(Python)

作者: 玖月晴 | 来源:发表于2020-12-01 10:33 被阅读0次
  1. 马在棋盘上的概率(Python)

题目

难度:★★★☆☆
类型:数组
方法:动态规划

力扣链接请移步本题传送门
更多力扣中等题的解决方案请移步力扣中等题目录

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

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

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

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

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

示例:

输入: 3, 2, 0, 0
输出: 0.0625
解释:
输入的数据依次为 N, K, r, c
第 1 步时,有且只有 2 种走法令 “马” 可以留在棋盘上(跳到(1,2)或(2,1))。对于以上的两种情况,各自在第2步均有且只有2种走法令 “马” 仍然留在棋盘上。
所以 “马” 在结束后仍在棋盘上的概率为 0.0625。

注意:

N 的取值范围为 [1, 25]
K 的取值范围为 [0, 100]
开始时,“马” 总是位于棋盘上

解答

方法1:动态规划

【矩阵定义】:定义一个K+1xNxN维度的三维矩阵dp,其中任意一点(k_, r_, c_)表示马走k_步后落在点(r_, c_)处的概率。这里在K维度上增加一维用来表示初始状态也就是马走零步的状态。

【初始状态】
由于马的最初位置是(r,c),因此马走零步落在点(r,c)的概率为1,因此填充dp[0][r][c] = 1,其他位置填充零。

【递推公式】
对于当前位置(r_, c_),马可以由八个方向跳过来:directions= [(2, 1), (2, -1), (1, 2), (1, -2), (-2, 1), (-2, -1), (-1, 2), (-1, -2)],对于每一个位置,马也可以等概率的跳到以上八个方向中任意一个。每一步的概率取决于上一步,每一个点的概率取决于八个特定方向临近点,因此,递推公式为:

dp[k_][r_][c_] = sum([dp[k_-1][r_+dr][c_+dc]/8 for dr, dc in directions])

这里需要注意判断求解概率的点不要越过棋盘边界。

【最终结果】

最后,我们选择最后一步的概率网格,求取网格所有点的和,即为K步后马还在棋盘中的概率。

class Solution:
    def knightProbability(self, N, K, r, c):
        dp = [[[0 for _ in range(N)] for _ in range(N)] for _ in range(K+1)]
        dp[0][r][c] = 1
        directions = [(2, 1), (2, -1), (1, 2), (1, -2),
                      (-2, 1), (-2, -1), (-1, 2), (-1, -2)
                      ]

        for k_ in range(1, K+1):
            print(dp[k_])
            for r_ in range(N):
                for c_ in range(N):
                    for dr, dc in directions:
                        if 0 <= r_+dr < N and 0 <= c_+dc < N:
                            dp[k_][r_][c_] += dp[k_-1][r_+dr][c_+dc] / 8
        return sum([prob for row in dp[-1] for prob in row])

方法2:记忆化深度优先搜索

为了简化计算,我们使用字典记录已经出现过的概率值,即将上述的三维网格按照位置-概率进行对应,通过及时的查找避免重复的计算。

这里用深度优先搜索方式代替动态规划,其一般规则是:首先判断特殊情况,例如越界或记录已经存在于字典中。注意这里dfs函数的返回值代表的是以从点(r,c)出发,K步后马还在棋盘上的概率,而非落在(r,c)点的概率。

class Solution:
    def knightProbability(self, N, K, r, c):

        memory = dict()
        directions = ((-1, -2), (-2, -1), (-2, 1), (-1, 2), (1, -2), (2, -1), (2, 1), (1, 2))

        def dfs(K, r, c):
            if not (0 <= r < N and 0 <= c < N):
                return 0
            if K == 0:
                return 1
            if (K, r, c) in memory:
                return memory[(K, r, c)]
            p = sum([dfs(K - 1, r + dr, c + dc) / 8.0 for dr, dc in directions])
            memory.update({(K, r, c): p})
            return p
        return dfs(K, r, c)

如有疑问或建议,欢迎评论区留言~

有关更多力扣中等题的python解决方案,请移步力扣中等题解析

相关文章

  • 688. 马在棋盘上的概率(Python)

    马在棋盘上的概率(Python) 题目 难度:★★★☆☆类型:数组方法:动态规划 力扣链接请移步本题传送门[htt...

  • 棋子

    是做棋盘上的棋子,还是要做执棋的棋手 人生如棋,谁都可以做棋盘上的棋子,但是做执棋的棋手可谓难于上青天。全局性的...

  • 棋行者

    传说有这样一个职业,叫棋行者,他们为棋疯,为棋狂,靠棋生。 他们喜欢旅行,喜欢冒险,不管是在棋盘上,还是生活中。 ...

  • 10 中国象棋术语大全

    中国象棋 中国传统棋种。在正方形的棋盘上分红、黑两方,各有16个子,为帅(将)一,仕(士)、相(象)、车、马、炮。...

  • C# 实现五子棋游戏(一)

    说到五子棋,相比大家都不会陌生;在一个棋盘上面,双方各执黑白一棋,首先在棋盘上面完成五个相同颜色的棋子连成一线,那...

  • 2020-08-27

    今天是星期四,妈妈给我们买了几套棋,有跳棋,有斗兽棋,还有飞行棋……我最喜欢玩的棋是斗兽棋和飞行棋,飞行棋盘上的图...

  • cocos2d-x3.14中国象棋AI(八)AI1

    我们要通过AI类计算下一步棋该如何走的话就必需让AI获得当前棋盘上棋子的局势、轮到谁执棋等各种棋盘上的信息,而这种...

  • 象棋盘上的马

    窝心马、屏风马、拐子马…… 这种种的标签 很容易让人想到这是匹“病”马 马在槽枥中的嘶叫 才能听出它的雄心 但它一...

  • 看马爸爸怎么在马叔叔的地盘上玩耍

    -支付宝官方微信公众号-欢迎页:山无棱,天地合,都不许取关!倒叙总结开始,因为正序翻了十分钟也没有翻到头,而且前面...

  • 使用 Min-Max 搜索和启发式评估函数实现五子棋 AI

    问题描述 五子棋AI。 设计一个交互式的应用,用户用鼠标在棋盘上单击左键表示落子,然后五子棋AI分析棋局,并在它认...

网友评论

      本文标题:688. 马在棋盘上的概率(Python)

      本文链接:https://www.haomeiwen.com/subject/atmdwktx.html