ACM: dp题(动态规划) poj 2151  (d…

来源:互联网 发布:深圳阿里云大厦 编辑:程序博客网 时间:2024/06/05 14:39

                                               Check the difficulty of problems

Description

Organizing a programming contest is not an easy job. To avoidmaking the problems too difficult, the organizer usually expect thecontest result satisfy the following two terms:
1. All of the teams solve at least one problem.
2. The champion (One of those teams that solve the most problems)solves at least a certain number of problems.

Now the organizer has studied out the contest problems, and throughthe result of preliminary contest, the organizer can estimate theprobability that a certain team can successfully solve a certainproblem.

Given the number of contest problems M, the number of teams T, andthe number of problems N that the organizer expect the championsolve at least. We also assume that team i solves problem j withthe probability Pij (1 <= i <= T,1<= j <= M). Well, can you calculatethe probability that all of the teams solve at least one problem,and at the same time the champion team solves at least Nproblems?

Input

The input consists of several test cases. The first line of eachtest case contains three integers M (0 < M<= 30), T (1 < T <=1000) and N (0 < N <= M). Each of thefollowing T lines contains M floating-point numbers in the range of[0,1]. In these T lines, the j-th number in the i-th line is justPij. A test case of M = T = N = 0 indicates the end of input, andshould not be processed.

Output

For each test case, please output the answer in a separate line.The result should be rounded to three digits after the decimalpoint.

Sample Input

2 2 2

0.9 0.9

1 0.9

0 0 0

Sample Output

0.972

 

题意: ACM比赛出M题,有T个队伍参加,比赛方希望每队至少做出一题,并且至少有一支队伍至少做N题.求概率.

解题思路:

               1. 设f[i][j] 是第i支队伍做出第j题的概率. g[i][j][k]是第i支队伍在前面j个题中做出了k道题的概率.

               2. 正难则反的思想. 既然要求每队至少做出一题的概率, 可以: 每队的1-g[i][m][0]相乘起来.

               3. 至少有一支队伍至少做N题. 可以这样求:

                   g[i][m][1] + g[i][m][2] + ...... + g[i][m][n-1]; (0<=i < T) 每支队伍乘起来

               4. 2和3的结果相减就是结果了.  (独立事件的求解方法.)

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 32
#define MAXSIZE 1005

double f[MAXSIZE][MAX];
double g[MAXSIZE][MAX][MAX];
int m, t, n;

int main()
{
//   freopen("input.txt","r",stdin);
   while(scanf("%d %d%d",&m,&t,&n) !=EOF && (m|t|n))
    {
      for(int i = 0; i < t; ++i)
      {
         for(int j = 1; j <= m; ++j)
            scanf("%lf",&f[i][j]);
      }
      
      memset(g,0,sizeof(g));
      for(int i = 0; i < t; ++i)
      {
         g[i][0][0] = 1;
         for(int j = 1; j <= m; ++j)
         {
            g[i][j][0] = g[i][j-1][0] * (1-f[i][j]);
            for(int k = 1; k <= j; ++k)
               g[i][j][k] = (g[i][j-1][k-1])*(f[i][j]) +(g[i][j-1][k])*(1-f[i][j]);
         }
      }
      
      double result = 1;
      for(int i = 0; i < t; ++i)
         result *= (1-g[i][m][0]);
      double tt = 1;
      for(int i = 0; i < t; ++i)
      {
         double sum = 0;
         for(int j = 1; j < n; ++j)
            sum += g[i][m][j];
         tt *= sum;
      }
      result -= tt;
      printf("%.3f\n",result);
    }
    return0;
}

0 0