21点游戏
使用 dfs + memo 的概率题
给一个 input num,随机抽1~10的数字加到 num 去得到新的 sum,如果 sum < 20 继续抽数字加和,20 <= sum <= 25 算 win,25 < sum 算 lose,求 lose probability.
dfs permutation 的思路加上 memo,每一层尝试用 num += 1~10,然后 recursion。应该需要算 probability 的平均值,所以 dfs 需要返回 avg prob 和一个 count 用来重新计算 avg prob
题目:backjack / 21 点, 给你一堆牌,从1到10,每张牌被抽的概率为1/10,问你dealer busted的概率是多少?
1. 如果dealer点数和不到17,将继续从牌堆抽牌;
2. 如果dealer点数和是在17-21,dealer stands,不继续抽牌;
3. 如果dealer点数和大于21,dealer busted;
条件2和条件3视为结束抽牌。
牌只有1-10点,如果还没满17点就要再拿一张,问超过21点的机率是多少?
DP问题,但面试时太紧张,不知道怎么设定DP,尤其是被一直抽牌有好几轮迷惑了。最后面试官提示,只要用DP计算拿到我点的机率,然后1-(P(17 )+ P(18)+ P(19)+ P(20)+ P(21))就好,还是太浅了我
https://www.1point3acres.com/bbs ... read&tid=496031
https://www.1point3acres.com/bbs/thread-424050-1-1.html
https://www.1point3acres.com/bbs/thread-311254-1-1.html
使用 dfs + memo 的概率题
给一个 input num,随机抽1~10的数字加到 num 去得到新的 sum,如果 sum < 20 继续抽数字加和,20 <= sum <= 25 算 win,25 < sum 算 lose,求 lose probability.
dfs permutation 的思路加上 memo,每一层尝试用 num += 1~10,然后 recursion。应该需要算 probability 的平均值,所以 dfs 需要返回 avg prob 和一个 count 用来重新计算 avg prob
题目:backjack / 21 点, 给你一堆牌,从1到10,每张牌被抽的概率为1/10,问你dealer busted的概率是多少?
1. 如果dealer点数和不到17,将继续从牌堆抽牌;
2. 如果dealer点数和是在17-21,dealer stands,不继续抽牌;
3. 如果dealer点数和大于21,dealer busted;
条件2和条件3视为结束抽牌。
牌只有1-10点,如果还没满17点就要再拿一张,问超过21点的机率是多少?
DP问题,但面试时太紧张,不知道怎么设定DP,尤其是被一直抽牌有好几轮迷惑了。最后面试官提示,只要用DP计算拿到我点的机率,然后1-(P(17 )+ P(18)+ P(19)+ P(20)+ P(21))就好,还是太浅了我
https://www.1point3acres.com/bbs ... read&tid=496031
https://www.1point3acres.com/bbs/thread-424050-1-1.html
https://www.1point3acres.com/bbs/thread-311254-1-1.html
| 我昨天才在二刷这题。。。 假设一次抽牌最多能抽到的数字是1-W 之间的数,而每个数字抽掉的概率都是一样的。因为能以一张牌的距离到达数字i 的方式只有i-1, i-2,...i-W, 要求抵达数字i的概率的话只要把i-1, i-2, ..., i-W的概率加总再除以W即可,也就是说去维护一个size为W的移动窗口就好了。 - dp 表示能到达i的概率 - dp = dp[i-1]/W + dp[i-2]/W +...+dp[i-W]/W - 用一个WSUM 表示dp[i-1]+...+dp[i-W] - 去维护这个WSUM,当i超过W以后每次loop 减去dp[i-W],加上dp。如果i 已经超过结束点就不必再加 - 最后的概率是结束点到胜利点之间的概率加总 补充内容 (2019-3-15 02:48): 好吧,没看清楚题目,好像和LC的有点不一样 |
根据LC Lee215 思路转来的,没跑过 unittest 求指正
先假设开始数字一定不是负数,一次可以抽1-10,
每个数字抽到的概率都是十分之一,可能抽到同样的数字,
20分含以上游戏结束,低于25分(包含)赢,高于25分输,
求游戏结束后输掉的概率.
psum 为所有能以一张牌达到 i 分分数的分数的概率总和
假如开头为 7
8 可以从 7 开始,psum = sum(dp[7])
9 可以从 7 或 8 开始 psum = sum(dp[7..8])
10 可以从 7,8,9 开始 psum = sum(dp[7..9])
18 可以从 8, 9, 10, ...17开始,但不能从7开始, psum = sum(dp[8..17])
每个数字抽到的概率都是十分之一,可能抽到同样的数字,
20分含以上游戏结束,低于25分(包含)赢,高于25分输,
求游戏结束后输掉的概率.
psum 为所有能以一张牌达到 i 分分数的分数的概率总和
假如开头为 7
8 可以从 7 开始,psum = sum(dp[7])
9 可以从 7 或 8 开始 psum = sum(dp[7..8])
10 可以从 7,8,9 开始 psum = sum(dp[7..9])
18 可以从 8, 9, 10, ...17开始,但不能从7开始, psum = sum(dp[8..17])
def the_21_game(start): if start >= 25: return 1.0 if start >= 20: return 1 - (25 - start) / 10 dp = [0] * 26 dp[start] = psum = 1.0 for i in range(start+1, 26): dp[i] = psum / 10 if i-10 >= start: psum -= dp[i-10] # 把dp[i-10] 去掉,因为下一个 i 不能从 i-10 开始 if i < 20: psum += dp[i] # 游戏在20分以后就结束了,不会有从20分开始到达下一个 i分的情况 return 1 - sum(dp[20:]) # 20-25 区间总和为赢的概率,1减去这个数值就是输的概率了def the_21_game2(): dp = [0] * 22 dp[0] = psum = 1.0 for i in range(1, 22): dp[i] = psum / 10 if i-10 >= 0: psum -= dp[i-10] if i < 17: psum += dp[i] return 1 - sum(dp[17:])