leetcode.837 新21点

837. 新21点

爱丽丝参与一个大致基于纸牌游戏 “21点” 规则的游戏,描述如下:

爱丽丝以 0 分开始,并在她的得分少于 K 分时抽取数字。 抽取时,她从 [1, W] 的范围中随机获得一个整数作为分数进行累计,其中 W 是整数。 每次抽取都是独立的,其结果具有相同的概率。

当爱丽丝获得不少于 K 分时,她就停止抽取数字。 爱丽丝的分数不超过 N 的概率是多少?

示例 1

输入:N = 10, K = 1, W = 10
输出:1.00000
说明:爱丽丝得到一张卡,然后停止。

示例 2

输入:N = 6, K = 1, W = 10
输出:0.60000
说明:爱丽丝得到一张卡,然后停止。
在 W = 10 的 6 种可能下,她的得分不超过 N = 6 分。

示例 3

输入:N = 21, K = 17, W = 10
输出:0.73278

提示:

  1. 0 <= K <= N <= 10000
  2. 1 <= W <= 10000
  3. 如果答案与正确答案的误差不超过 10^-5,则该答案将被视为正确答案通过。
  4. 此问题的判断限制时间已经减少。

这道题真的就有点难

 说一下解题思路
 /*
 * 例如N=3,K=2,W=3 我们要求的实际是 i=[1,2,3]中,i=2的概率+i=3的概率
 * 我们可以从头开始推,当手中没有牌时,你抽到1的概率是 1/3也就是dp[1]=1/w
 * 当i=2时的方法有两种: 手中牌是0, 你直接抽到2 这时概率是 A=1/3=1/w
 *                                        手中牌是1, 你抽到1 这时的概率是 B=1/3*1/3=(1/w)*(1/w) 这里用的是条件概率的算法
 * 最终 dp[2]=A+B 
 * 因为当i<=w的时候,你是可以直接抽到一张牌符合结果的
 * 所以,当i<=w的时候 dp[1]=1/w,dp[2]=dp[1]*1/w+1/w,dp[3]=dp[1]*1/w+dp[2]*1/w+1/w ... dp[i] = sum(dp[1,i-1])/w+1/w                         
 * 当i>w的时候没有办法取一次得到结果,所以不用加上1/w了,例如:N=6,K=4,W=2
 * 当i=3时,有2种取法1+2,2+1 没有办法从0直接到3,也就没有1/w了
 *   dp[1]=1/w,dp[2]=dp[1]/w+1/w,dp[3]=sum(dp[1,2])/w
 * 当i=4时有两种取法2+2,3+1   , dp[4]=sum(dp[2,3])/w=(sum(dp[1,3])-dp[1])/w=(sum(dp[w+1,i])-dp[i-w])/w
 * 因为i的最大值是N所以dp的长度就是N+1
 * 最终解为sum(dp[K,N])
 * 而当N >=(K + W)时 所有种k和w的和都不会超出N所以解是 1
 */

 

#include <iostream>

using namespace std;

double new21Game(int N, int K, int W) {

	int i;
	double dp[10002];
	double sum = 0;
	dp[0] = 1;
	if(K > 0){
		sum = sum + 1;
	}
	for(i = 1; i <= N; i++){
		dp[i] = sum / W;
		if(i < K){
			sum += dp[i];
		}
		if(i >= W){
			sum -= dp[i - W];
		}
	}
	double ans = 0;
	for(i = K; i <= N; i++){
		ans += dp[i];
	}
	return ans;

}


int main(){
	double re = new21Game(21, 17, 10);
	cout << re << endl;
}






 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值