poj2151 dp求概率

题意:有T个人参加比赛,共有M道题,第 i 个人通过第 j 题的概率为 p[i][j]
求:所有人都至少做出一道题,而且第一名至少做出N道,求这个结果的概率
分析:可以知道,每个人自己是互不影响的 对于一个选手 i 前 j 道题,做出 k 道题的概率F[i][j][k] = F[i][j - 1][k - 1] * p[i][j] + F[i][j - 1][k] * (1 - p[i][j])
那么问题可以转化为:所有至少做出一道的概率(p1) - 所有选手做出的题数n >= 1 && n < N 的概率(p2)
设s[i][j]表示F[i][M][0] + F[i][M][1] + ... + F[i][M][j]
P1 = (s[1][M] - s[1][0])*(s[2][M]-s[2][0])*...*(s[T][M]-s[T][0])
P2 = (s[1][N-1] - s[1][0])*(s[2][N-1]-s[2][0])*...*(s[T][N-1]-s[T][0])

以上内容摘自博客   http://www.cnblogs.com/ylfdrib/archive/2010/12/03/1895811.html

我的代码:

#include <iostream>
#include <cstdio>

using namespace std;

float p[1003][33], dp[1003][33][33];

float DP(int m, int t, int n)
{
    int i, j, k;

    //初始化第一道题没做对和做对时的概率
    for (i = 1; i <= t; i++) {
        dp[i][1][0] = 1 - p[i][1];
        dp[i][1][1] = p[i][1];
    }
    //初始化前k道题一道题都没做对的概率
    for (i = 1; i <= t; i++)
        for (j = 2; j <= m; j++)
            dp[i][j][0] = dp[i][j-1][0] * (1 - p[i][j]);
    //dp求第i队前j道做对k道的概率
    for (i = 1; i <= t; i++)
        for (j = 2; j <= m; j++)
            for (k = 1; k <= j; k++) {
                if (k < j)
                   dp[i][j][k] = dp[i][j-1][k-1] * p[i][j] + dp[i][j-1][k] * (1 - p[i][j]);
                else dp[i][j][k] = dp[i][j-1][k-1] * p[i][j];
            }
    float p1 = 1, p2 = 1, tmp;

    //求p1,即所有队都至少做一题的概率
    for (i = 1; i <= t; i++) p1 *= (1 - dp[i][m][0]);
    //求p2,即所有队伍都做x(1 <= x < n)道的概率。
    for (i = 1; i <= t; i++) {
        tmp = 0;
        for (j = 1; j < n; j++)
            tmp += dp[i][m][j];
        p2 *= tmp;
    }
    return p1 - p2;
 }

int main()
{
    int m, t, n, i, j;

    while (scanf ("%d%d%d", &m, &t, &n)) {
         if (!m && !t && !n) break;
         for (i = 1; i <= t; i++)
            for (j = 1; j <= m; j++)
                 scanf ("%f", &p[i][j]);
         printf ("%.3f\n", DP(m, t, n));
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值