POJ 2151 Check the difficulty of problems(概率dp)

版权声明:听说这里让写版权声明~~~ https://blog.csdn.net/m0_37691414/article/details/82153561

题意:在acm比赛中,n题,t队。给出每个队做对每题的概率,问每队至少对一题,至少有一队做对至少m题的概率。(本解题报告中的n,m与原题中相反)

解析:dp,f[i][j]表示第i个队伍做对第j题的概率。g[i][j][k]表示第i个队伍对于前j题而言做对k道的概率。

g[i][j][k] = g[i][j - 1][k - 1] * (f[i][j]) + g[i][j - 1][k] * (1 - f[i][j]);

有了所有的g,我们就可以求出每个队至少做对1题的概率:ans *= 1 - g[i][n][0];
再减去每个队都只做对1~m-1题的概率(把每个队做对1~m-1题的概率加和,并把各队结果相乘)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 35;
const int maxt = 1005;
int n, t, m;
double f[maxt][maxn];
double dp[maxt][maxn][maxn];
int main(){
	while(~scanf("%d%d%d", &n, &t, &m), n | t | m){
		double ans = 1;
		for(int i = 0; i < t; ++i)
			for(int j = 1; j <= n; ++j)
				scanf("%lf", &f[i][j]);
		memset(dp, 0, sizeof(dp));
		for(int i = 0; i < t; ++i){
			dp[i][0][0] = 1;
			for(int j = 1; j <= n; ++j){
				dp[i][j][0] = dp[i][j - 1][0] * (1 - f[i][j]);
				for(int k = 1; k <= j; ++k)
					dp[i][j][k] = dp[i][j - 1][k - 1] * (f[i][j])+ dp[i][j - 1][k] * (1 - f[i][j]);
			}
		}
		for(int i = 0; i < t; ++i)
			ans *= 1 - dp[i][n][0];
		double temp = 1;
		for(int i = 0; i < t; ++i){
			double sum = 0;
			for(int j = 1; j < m; ++j)
				sum += dp[i][n][j];
			temp *= sum;
		}
		ans -= temp;
		printf("%.3f\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37691414/article/details/82153561