标签:概率dp
开锁魔法II | ||||||
|
||||||
Description | ||||||
一日,崔克茜来到小马镇表演魔法。 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它。崔克茜可以通过魔法,暴力打开一个盒子。但是崔克茜最多只可以使用 k 次魔法,问在 k 次魔法内,打开所有盒子的概率是多少。 |
||||||
Input | ||||||
多组测试数据。 每组数据第一行有一个整数 n 和一个整数 k。(1 <= k <= n?<= 5000) |
||||||
Output | ||||||
对于每组数据,输出一行表示对应的答案。结果保留四位小数。 | ||||||
Sample Input | ||||||
3 1 3 2 3 3 10 3 |
||||||
Sample Output | ||||||
0.3333 0.8333 1.0000 0.7061 |
||||||
Source | ||||||
哈尔滨理工大学第五届ACM程序设计竞赛 |
Submit | Statistic | Discuss | Sharedcodes
|
令d[i][j]表示前i把锁必须要用j次魔法打开的概率,不难看出dp[i][j]转移有两个来源,一个是前i-1把锁用了j次魔法,此时打开的前i-1个箱子里一定有一把钥匙是第i个箱子的(否则无法在j次魔法的情况下打开第i个盒子),概率为(i-1)/i,另一种情况就是前i-1个箱子用了j-1次魔法,前i-1个箱子里的钥匙一定不能打开第i把锁(否则只需要j-1次魔法就能打开前i个箱子),概率为1/i。最后的结果应该是d[n][1]+d[n][2]+...d[n][k]。
#include <stdio.h> #include <string.h> #include <stdlib.h> const int maxn = 5e3 + 5; double d[maxn][maxn]; void init(int n) { memset(d,0,sizeof d); d[0][0] = 1; for(int i = 1; i <= n; i++) for(int j = 1; j <= i; ++j) { d[i][j] = (d[i-1][j]*(i-1)+d[i-1][j-1])/i; } for(int i = 2;i <= n; ++i) for(int j = 1; j <= i; ++j) d[i][j] += d[i][j-1]; } int main(int argc, char const *argv[]) { int n,k; init(5000); while(~scanf("%d%d",&n,&k)) printf("%.4f\n",d[n][k]); return 0; }
标签:概率dp
原文地址:http://blog.csdn.net/acvcla/article/details/44999999