标签:概率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