• poj 2151 Check the difficulty of problems 概率dp


    点我看题

    n个队伍, m道题, 给出所有队伍可以做出每道题的概率, 求所有队伍做出的题数>=1并且冠军队伍做出的题数必须大于等于k。

    首先, dp[i][j][k]表示第i支队伍在前j道题里做出k道题的概率, dp[i][j][k] = dp[i][j-1][k-1]*p[i][j]+dp[i][j-1][k]*(1-p[i][j]); 很容易可以推出这个式子。

    s[i][j]表示第i支队伍做出j道题的概率, 那么s[i][j] = dp[i][m][j]。

    另p1 = 所有队伍做出题数大于0的概率, p2 = 所有队伍做出的题数在1~k-1之间的概率, 那么最终结果就为p1-p2。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mem(a) memset(a, 0, sizeof(a))
     4 double dp[1005][35][35], s[1005][35], p[1005][35];
     5 int main()
     6 {
     7     int n, m, k;
     8     while(cin>>m>>n>>k) {
     9         if(n+m+k==0)
    10             break;
    11         for(int i = 1; i<=n; i++) {
    12             for(int j = 1; j<=m; j++) {
    13                 scanf("%lf", &p[i][j]);
    14             }
    15         }
    16         mem(dp);
    17         for(int i = 1; i<=n; i++) {
    18             dp[i][0][0] = 1.0;                  //显然每个队伍在前0题做出0题的概率为1
    19         }
    20         for(int i = 1; i<=n; i++) {
    21             dp[i][n][0] = 1.0;
    22             for(int j = 1; j<=m; j++) {
    23                 dp[i][m][0] *= (1-p[i][j]);     //每个队伍在前m题做出0题的概率
    24             }
    25         }
    26         for(int i = 1; i<=n; i++) {
    27             for(int j = 1; j<=m; j++) {
    28                 for(int k = 0; k<=j; k++) {
    29                     if(k)
    30                         dp[i][j][k] = dp[i][j-1][k-1]*p[i][j] + dp[i][j-1][k]*(1-p[i][j]);   //状态转移, k=0时要特判一下
    31                     else
    32                         dp[i][j][k] = dp[i][j-1][k]*(1-p[i][j]);
    33                 }
    34             }
    35         }
    36         for(int i = 1; i<=n; i++) {
    37             for(int j = 0; j<=m; j++) {
    38                 s[i][j] = dp[i][m][j];
    39                 if(j != 0) {
    40                     s[i][j] += s[i][j-1];    //这里我求的前缀和,后面求在1~k-1之间的概率时可以直接相减
    41                 }
    42             }
    43         }
    44         double p1 = 1, p2 = 1;
    45         for(int i = 1; i<=n; i++)
    46             p1 *= (1-s[i][0]);
    47         for(int i = 1; i<=n; i++)
    48             p2 *= (s[i][k-1]-s[i][0]);
    49         printf("%.3f
    ", p1-p2);
    50     }
    51 }
  • 相关阅读:
    SQL 2005的ROW_NUMBER()实现分页的功能
    UML建模工具集
    挽救崩溃的WinXP操作系统四招
    16个经典面试问题回答思路
    自动关闭弹出式窗口
    在winform中嵌入Flash(swf)的方法及常见问题的解决
    C#获取安装程序所在的路径
    转载:C#操作注册表
    C#实现Dll(OCX)控件自动注册的两种方法
    转载:C#创建和修改注册信息
  • 原文地址:https://www.cnblogs.com/yohaha/p/5014100.html
Copyright © 2020-2023  润新知