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

题意:略;

分析:见code

个人想法:  面对%.3lf而WA无数次的我我,只想说:"我有一句***不知当讲不当讲..."

/**
 * 概率dp
 * c个问题,n支队伍, 冠军要求解题数m
 * 求所有队伍至少解出一题以及至少有一支队伍(冠军)做出M道题的概率P
 * 设 概率A: 所有队伍都至少解出一题
 *    概率B: 所有队伍都至少解出一题但至多解出M-1题
 * 则可知:
 * P = A-B
 * 求A: 每个队伍至少做出一题的概率的乘积
 * 求B:利用dp思想;
 *      所有队伍都至少解出一题但至多解出M-1题
 *      转化成, 解出1题,解出2题,解出3题......解出M-1题;
 *      设ans[i][j][k]: i表示第i支队伍, j表示第i支队伍做前j题, k表示前j题做出了k道题
 *      则推出方程为:
 *      ans[i][j][k] = ans[i][j-1][k]*(1-p[i][j]) + ans[i][j-1][k-1]*p[i][j];
 *      即
 *      前j-1道题已经做出了k道题, 则第j道题不必做出即可满足前j道题做出k道题
 *      +
 *      前j道题已经做出了k-1道题, 则第j道题须做出来才能满足前j道题做出k道题
 * 则 B = (ans[i][c][1~M-1])累加和 (i = 1, 2, 3, 4, ... n); 
 */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn = 1005;
int n, m, c;
double ans[maxn][40][40];
double p[maxn][40];
void solve(){
	int i=1, j, k;
	for(i=1; i<=n; i++){ //第i支队伍
		ans[i][0][0] = 1.0;
		for(j=1; j<=c; j++) ans[i][j][0] = ans[i][j-1][0]*(1-p[i][j]);
		for(j=1; j<=c; j++){//前j题
			for(k=1; k<=j; k++){
				ans[i][j][k] = ans[i][j-1][k]*(1-p[i][j]) + ans[i][j-1][k-1]*p[i][j];
				// cout << ans[i][j][k]<<endl;
			}
		}
		// cout <<"***********\n";
	}
	return ;
}
int main(){
	//freopen("in.txt", "r",stdin);
	int i, j, k;
	/*c个问题,n支队伍, 冠军要求解题数m*/
	
	while(~scanf("%d %d %d", &c, &n, &m), c||n||m){
		double A=1.0, B=1.0, tmp=1.0;
		memset(ans, 0, sizeof(ans));
		memset(p, 0, sizeof(p));
		for(i=1; i<=n; i++){
			for(j=1; j<=c; j++){
				scanf("%lf", &p[i][j]);
			}
		}
		solve();
		for(i=1; i<=n; i++){
			A*=(1-ans[i][c][0]);//每只队伍至少做出一题的概率
			tmp = 0;
			for(k=1; k<=m-1; k++){
				tmp += ans[i][c][k];
			}
			B *= tmp;
			// cout <<"*********\n";
		}
		// cout <<"*********\n";
		printf("%.3f\n", A-B);//POJ上%.3lf会WA...
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值