Codeforces 859D Third Month Insanity 概率DP

来源:互联网 发布:qq三国70js橙鬼 编辑:程序博客网 时间:2024/06/13 18:40

题目链接:http://codeforces.com/contest/859/problem/D

题意:一个排球比赛,开始2^n个队,淘汰制,每一把比赛淘汰一半的人,然后给出了每个人赢其他人的概率,问一个人正确预测比赛结果的最大期望是多少?

解法:概率DP好题。比较久没写过概率DP了。复习一下,概率DP一般是dp[i]代表i到终点的期望,然后dp[i] = sigma(dp[j]+代价)*概率。。这道题比较特殊,我们可以把比赛过程看成在二叉树上的概率DP。win[i][j]表示在根节点为i第j个人赢的概率,e[i][j]代表第根节点为i第j个赢的期望,pro[i][j]表示第i个人赢第j个人的概率。然后按照概率DP的基本方法转移即可。


#include <bits/stdc++.h>using namespace std;const int maxn = 1010;double win[maxn][maxn], e[maxn][maxn], pro[maxn][maxn];int n, m, x;void DFS(int p, int l, int r){    if(l+1==r) win[p][l]=1,e[p][l]=0;    else{        int mid=(l+r)/2;        DFS(p*2, l, mid);        DFS(p*2+1, mid, r);        for(int i=l; i<mid; i++)            for(int j=mid; j<r; j++)                win[p][i] += win[p*2][i]*win[p*2+1][j]*pro[i][j];        for(int i=l; i<mid; i++)            for(int j=mid; j<r; j++)                e[p][i] = max(e[p][i], win[p][i]*(r-l)/2+e[p*2][i]+e[p*2+1][j]);        for(int i=mid; i<r; i++)            for(int j=l; j<mid; j++)                win[p][i] += win[p*2+1][i]*win[p*2][j]*pro[i][j];        for(int i=mid; i<r; i++)            for(int j=l; j<mid; j++)                e[p][i] = max(e[p][i], win[p][i]*(r-l)/2+e[p*2+1][i]+e[p*2][j]);    }}int main(){    scanf("%d", &n);    m = 1<<n;    for(int i=0; i<m; i++){        for(int j=0; j<m; j++){            scanf("%d", &x);            pro[i][j] = 0.01*x;        }    }    DFS(1, 0, m);    double maxv = 0;    for(int i=0; i<m; i++) maxv = max(maxv, e[1][i]);    printf("%.10f\n", maxv);    return 0;}


原创粉丝点击