【poj 2151】Check the difficulty of problems 概率dp

10 篇文章 0 订阅
9 篇文章 0 订阅

题意:m到题T个队伍,给出每一个队伍做出每一道题的概率,询问所有队伍都至少解决一道题目且做的最多的队伍做的题目大于等于n的概率。

感觉还是一道很有趣的dp。首先考虑求至少每一个队伍都至少解决一道题目可以怎么解决?这个很简单,可以先算出每个队一道题都解决不了,然后用1减去就可以了。现在考虑至少有一个队伍要求解决的题目的数目超过n该如何解决,类似于刚才的想法我们社p为所有队伍都解决不了超过等于n道题的概率所以最后的答案就是p1*(1-p)换出来就是p1-p1*p

可以用f[i][j][k]表示第i个人对于钱j道题解决了k道题的概率与处理出每一个人做k道题的概率(即f[i][m][k])方程:

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

为了方便令dp[i][j]表示第i个人最多做j道题的概率(用刚才的转移就好了)

最后统计一下答案就好了

#include<cstdio>
#include<cstring>
#include<iostream>
#define clean(a)  memset(a,0,sizeof(a))
using namespace std;
int T,m,n;
double f[1002][32][32],dp[1002][32],mat[1002][32];
//f[i][j][k]表示对于第i个队伍 前j个题目解出了k道题目的概率
//dp[i][j] 表示第i个队伍至少做出j道题目的几率 

int main(){
	while(scanf("%d%d%d",&m,&T,&n)&&(m+T+n)){
		clean(f),clean(dp),clean(mat);
		for(int i=1;i<=T;i++){
			f[i][0][0]=1.0;
			for(int j=1;j<=m;j++)
				scanf("%lf",&mat[i][j]);
		}
		for(int i=1;i<=T;i++){
			for(int j=1;j<=m;j++){
				for(int k=0;k<=j;k++){
					f[i][j][k]=f[i][j-1][k]*(1-mat[i][j]);
					if(k!=0)f[i][j][k]+=f[i][j-1][k-1]*mat[i][j];
				}
			}
		}
		for(int i=1;i<=T;i++){
			dp[i][0]=f[i][m][0];
			for(int j=1;j<=m;j++)dp[i][j]=f[i][m][j]+dp[i][j-1];
		}
		double ans1=1,ans2=1;
		for(int i=1;i<=T;i++){
			ans1*=1-dp[i][0];
			ans2*=(dp[i][n-1]-dp[i][0]);
		}
		printf("%.3lf\n",ans1-ans2);
	}
	return 0;
}/*
2 2 2
0.9 0.9
1 0.9
0 0 0
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值