问题 G: 新21点
时间限制: 1 Sec 内存限制: 128 MB
题目链接:http://acm.lsnu.edu.cn/oj/problem.php?id=2499
题目描述
玩家参与一个大致基于纸牌游戏 “21点” 规则的游戏,描述如下:
以 0 分开始,在得分少于 K 分时抽取数字。 抽取时,从 [1, W] 的范围中随机获得一个整数作为分数进行累计。 每次抽取都是独立的,其结果具有相同的概率。
当获得不少于 K 分时,就停止抽取数字。 求解分数不超过 N 的概率是多少?
输入
输入仅有一行,包括三个整数 N,K,W ( 0 <= K <= N <= 1000, 1 <= W <= 10000 ) 。
输出
输出一个浮点数,请保留 5 位小数,表示分数不超过 N 的概率。
样例:
样例输入
6 1 10
样例输出
0.60000
提示
如果答案与正确答案的误差不超过 ,则该答案将被视为正确答案通过。
思路:
这是一道动态规划的题,说实话对这道题理解还不够,先附上赛后题解吧。
赛后题解:
/*
动态规划,dp[i] 表示分数为 i 的概率,dp[i] = (dp[i-1] + dp[i-2] + ... + dp[i-W]) / W,
每次计算dp[i] 不能真的去进行 W 次累加,分母不变,分子可以维护一个前缀和 s, 这样递推即为线性时间复杂度。
*/
# include <stdio.h>
# define MIN(x, y) (((x) < (y)) ? (x) : (y))
int main() {
int n, k, w, i;
double dp[100000] = {0.0}, s = 0;
scanf("%d%d%d", &n, &k, &w);
for (i = 0; i < k; i++) {
if (i < w) {
dp[i] = (s + MIN(n - k + 1, w - i)) / w;
} else {
dp[i] = s / w;
s -= dp[i - w];
}
s += dp[i];
}
printf("%.5lf\n", dp[k - 1]);
return 0;
}