Alice plays the following game, loosely based on the card game "21".
Alice starts with 0
points, and draws numbers while she has less than K
points. During each draw, she gains an integer number of points randomly from the range [1, W]
, where W
is an integer. Each draw is independent and the outcomes have equal probabilities.
Alice stops drawing numbers when she gets K
or more points. What is the probability that she has N
or less points?
Example 1:
Input: N = 10, K = 1, W = 10 Output: 1.00000 Explanation: Alice gets a single card, then stops.
Example 2:
Input: N = 6, K = 1, W = 10 Output: 0.60000 Explanation: Alice gets a single card, then stops. In 6 out of W = 10 possibilities, she is at or below N = 6 points.
Example 3:
Input: N = 21, K = 17, W = 10 Output: 0.73278
Note:
0 <= K <= N <= 10000
1 <= W <= 10000
- Answers will be accepted as correct if they are within
10^-5
of the correct answer. - The judging time limit has been reduced for this question.
---------------------------------------------------------------------
直接搞N*W的复杂度肯定会超时,这题要优化到O(N)的复杂度,有两种思路:
思路一,滑动窗口:,位置i的概率是有[i-1,i-W]跳过去的,因此是1/W*sum([i-1,i-W]),注意[i-1,i-W]这个区间窗口滑动滑动就滑不下去了,因此过滤掉边界即可:
class Solution:
def new21Game(self, N, K, W):
if K == 0 or N >= K + W: return 1
dp = [1.0] + [0.0] * N
sliding = 1.0
for i in range(1, N + 1):
dp[i] = sliding / W
if i < K: sliding += dp[i]
if i - W >= 0: sliding -= dp[i - W]
#print("sliding={0}".format(sliding))
return sum(dp[K:])
思路二,动态规划:如果起点位于闭区间[K,N],那么 the probability that she has N
or less points is 1, i.e., f(x)=1 when K<=x<=N, f(x)=0 when x>N. 其中f(x)表示起点从x开始,the probability that she has N
or less points,最后求f(0)就可以。f(x)=1/W*(f(x+1)+...f(x+W)),而f(x-1)=1/W*(f(x)+...f(x+W-1)),这样根据f(x)和f(x-1)就可以得到O(1)的递归公式。那么codes是
class Solution(object):
def new21Game(self, N, K, W):
dp = [0.0] * (N + W + 1)
# dp[x] = the answer when Alice has x points
for k in xrange(K, N + 1):
dp[k] = 1.0
S = min(N - K + 1, W)
# S = dp[k+1] + dp[k+2] + ... + dp[k+W]
for k in xrange(K - 1, -1, -1):
dp[k] = S / float(W)
S += dp[k] - dp[k + W]
return dp[0]