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

来源:互联网 发布:强力手机数据恢复软件 编辑:程序博客网 时间:2024/05/28 05:16

题目链接:点击打开链接

题意:ACM比赛中, 有T个队, m道题, 每个队能解出每道题的概率已知, 求每个队至少解出一道题并且冠军队解出至少n道题的概率。

思路:首先, 我们不难想到用d[i][j]表示前i个队, 冠军队解出了j道题的概率。 那么答案就是sum(a[n][j]) j >= n 。  每次转移的代价是, 决策第i个队解决了多少道题, 并且更新j(冠军队的解题数)。 那么难点就在于怎么求出第i个队解出j个题的概率。   我们再求一次DP, 用x[i][j][k]表示,第i个队在前j个题中解出了k个题的概率。  那么转移就是x[i][j][k] = x[i][j-1][k-1] * a[i][j] + x[i][j-1][k] * a[i][j]。 边界条件是:

1.  x[0][0][0] = 1,表示前0个队解出0题,  这是显然的。

2.  还有一个就是x[i][j][0] = (1-a[i][1]) * (1-a[i][2]) * ...... * (1 - a[i][j])。

细节参见代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<stack>#include<bitset>#include<cstdlib>#include<cmath>#include<set>#include<list>#include<deque>#include<map>#include<queue>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;typedef long long ll;typedef long double ld;const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;const int mod = 1000000000 + 7;const int INF = 0x3f3f3f3f;const int seed = 131;const ll INF64 = ll(1e18);const int maxn = 1000 + 10;int T,n,m,vis[maxn][33],kase = 0;double a[maxn][33],x[maxn][33][33], d[maxn][33];double dp(int i, int j) {    double& ans = d[i][j];    if(i == T + 1) return j >= n ;    if(vis[i][j] == kase) return ans;    vis[i][j] = kase;    ans = 0;    bool ok = false;    for(int k = 1; k <= m; k++) {        ans += dp(i+1, max(j, k)) * x[i][m][k];    }    return ans;}int main() {    while(~scanf("%d%d%d",&m,&T,&n) && (m || T || n)) {        for(int i=1;i<=T;i++) {            for(int j=1;j<=m;j++) scanf("%lf",&a[i][j]);        }        memset(x, 0, sizeof(x));        ++kase;        for(int i=1;i<=T;i++) {            x[i][0][0] = 1;            for(int j=1;j<=m;j++) {                x[i][j][0] = x[i][j-1][0] * (1 - a[i][j]);            }            for(int j=1;j<=m;j++) {                for(int k=1;k<=j;k++) {                    x[i][j][k] = x[i][j-1][k-1] * a[i][j];                    if(j-1 >= k) x[i][j][k] += x[i][j-1][k] * (1 - a[i][j]);                }            }        }        double ans = dp(1, 0);        printf("%.3f\n",ans);    }    return 0;}


1 0
原创粉丝点击