参考了:https://zhuanlan.zhihu.com/p/86167813
题意:初始是0点,每次可以从[1, W]中随机出一个数字,累加上去,直到自己的点数 > K, 求这个时候点数 <= N的概率
我们使用动态规划来做:
dp[i]表示我们达到点数为i的概率,注意到当 i >= K + W的时候 , dp[i] = 0,
考虑dp[i]怎么求,点数i可以由i-1加1得到,可以由i-2加2得到等等
dp[i] = dp[i-1] * 1/W + dp[i-2] * 1/W + ... + dp[i-W] * 1/W
实际上呢这个式子是有一定的使用条件的,以题目中的
N = 21, K = 17, W = 10
来举例,当i=12的时候,是没问题的
dp[12] = 1/10(dp[11] + dp[10] + .. dp[2])
当i比较小的时候 dp[3] = 1/10(dp[2] + dp[1] +dp[0]), 也就是说当i比较小的时候,后面的项比较少
当i大于K的时候呢?比如i=20
注意这个时候20是不能从19+1得到的,因此19的时候已经 19 > 17=K了,我们只能从最大是K-1的递推过来
dp[20] = 1/10*(dp[16] +dp[15] +...+ dp[10])
题目要求的是什么呢?
是在点数X>=K的时候X<=N的概率,这是一个条件概率,即P(X<=N | X>=K)
根据贝叶斯公式:
P(X<=N | X>=K) = P(X<=N and X>=K) / P(X >= K)
分子是P(K) + P(K+1) + ...+P(N)
分母是P(K) + P(K+1) +...+P(K+W-1),因为i >= K + W的时候 , P(i)为0
下面是一个实现的代码:
public double new21Game(int N, int K, int W) {
double[] d = new double[K + W ];
d[0] = 1;
for (int i = 1; i <= K; i++) {
double s = 0;
for (int j = 1; j <= W; j++) {
if (i - j < 0) break;
s += d[i - j];
}
d[i] = s / W;
}
for (int i = K + 1; i <= K + W - 1; i++) {
double s = 0;
for (int j = K - 1; j >= 0; j--) {
int dif = i - j;
if (dif > W) break;
s += d[j];
}
d[i] = s / W;
}
double fenzi = 0;
double fenmu = 0;
for (int i = K; i <= K + W - 1; i++) fenmu += d[i];
for (int i = K; i <= Math.min(N, K + W - 1); i++) fenzi += d[i];
return fenzi / fenmu;
}
由于N, K<=10000, 这个O((N+K)^2)是会超时的,使用前缀和优化到O(N+K)
public double new21Game(int N, int K, int W) {
double[] d = new double[K + W];
double[] sum = new double[K + W];
d[0] = 1;
sum[0] = 1;
for (int i = 1; i <= K; i++) {
double s;
if (i <= W) s = sum[i - 1];
else s = sum[i - 1] - sum[i - 1 - W];
d[i] = s / W;
sum[i] = sum[i - 1] + d[i];
}
for (int i = K + 1; i <= K + W - 1; i++) {
int upBound = K - 1;
double sup = upBound >= 0 ? sum[upBound] : 0;
int lowBound = (i - W - 1);
double s = sup - (lowBound >= 0 ? sum[lowBound] : 0);
d[i] = s / W;
sum[i] = sum[i - 1] + d[i];
}
double fenzi = 0;
double fenmu = 0;
for (int i = K; i <= K + W - 1; i++) fenmu += d[i];
for (int i = K; i <= Math.min(N, K + W - 1); i++) fenzi += d[i];
return fenzi / fenmu;
}