POJ 2151(概率DP)

题目链接:http://poj.org/problem?id=2151

题意:t支队伍m个题,求在每支队伍至少完成一道题的情况下冠军队伍至少完成n个题的概率。

思路:

这道题一开始是放在哈希的题目列表里面..看完题后感觉完全和哈希没关系呃..

感觉又是#没有思路无法下手,有了思路就会觉得很简单系列#的一道题,好纠结...


用dp[i][j][k]表示第i支队伍在前j道题中完成k道题的概率

易得dp[i][j][k]=dp[i][j-1][k-1]*a[i][j]+dp[i][j-1][k]*(1-a[i][j]);

初始化:

dp[i][0][0]=1.0;(即第i支队伍在前0道题中完成0道题的概率始终为1)

dp[i][j][0]=dp[i][j-1][0]*(1-a[i][j]);


ans=所有队伍至少完成一道题的概率(即1-dp[i][m][0])-所有冠军队伍均完成至少n个题的概率(即t支队伍dp[i][m][1...n-1]的乘积);

(之所以用减号而不是乘号是因为前者的概率中包含后者)

最后还要注意:

冠军队伍可能不只一支

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=1005;
int m,t,n;
double dp[maxn][35][35];
double a[maxn][35];

void Read(){
	for(int i=1;i<=t;i++)
		for(int j=1;j<=m;j++)
			scanf("%lf",&a[i][j]);
}

void init(){
	memset(dp,0,sizeof(0));
	for(int i=1;i<=t;i++)
		dp[i][0][0]=1.0;
	for(int i=1;i<=t;i++){
		for(int j=1;j<=m;j++){
			dp[i][j][0]=dp[i][j-1][0]*(1-a[i][j]);
		}
	}
}

void Dynamic_Programming(){
	for(int i=1;i<=t;i++){
		for(int j=1;j<=m;j++){
			for(int k=1;k<=m;k++){
				dp[i][j][k]=dp[i][j-1][k-1]*a[i][j]+dp[i][j-1][k]*(1-a[i][j]);
			}
		}
	}
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
#endif
	while(~scanf("%d%d%d",&m,&t,&n)){
		if(m==0&&t==0&&n==0) break;
		Read();
		init();
		Dynamic_Programming();
		double ans=1.0;
		for(int i=1;i<=t;i++)
			ans*=1-dp[i][m][0];
		double pro=1.0;
		for(int i=1;i<=t;i++){
			double sumPro=0.0;
			for(int j=1;j<=n-1;j++){
				sumPro+=dp[i][m][j];
			}
			pro*=sumPro;
		}
		ans-=pro;
		printf("%.3f\n",ans);
	}
	return 0;
}


你可能感兴趣的:(POJ 2151(概率DP))