POJ3071题解(概率dp)

原创 2018年04月17日 00:01:24

POJ3071题解

题意

给定正整数n,共有2^n支球队,按照二分顺序比赛,给定球队i对球队j的胜率,问哪只球队有最大几率获胜。

笺释

这道题还是很好的体现了动态概率思想。
从最朴素的想法来说,P[球队i获胜]=P[球队i赢第1局]P[球队i赢第2局]…*P[球队i赢第n局]
球队i赢第1局的概率根据数据可直接获得,来考虑球队i赢第j局的概率。
设dp[i][j]为在第i轮球队j获胜的概率。

dp[i][j]+=dp[i-1][j]*dp[i-1][rival[i][j][k]]*P[j][rival[i][j][k]]

其中rival[i][j][k]意为在第i轮球队j的第k个对手,分析可知k=2^i-1,只需要预处理出rival矩阵然后就能顺利进行dp。

完整代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 150
using namespace std;
int rival[8][MAXN][MAXN/2],n;
double P[MAXN][MAXN];
double dp[8][MAXN];
void init(int s,int e,int tn)
{
    if(tn==0)
    {
        return;
    }
    if(s==e)
    {
        return;
    }
    //在第2轮 对手有2种可能性
    //在第tn轮 对手有2^n-1种可能性
    int mid=(s+e)/2;
    //mid定义为中间分开的前面一个
    int m=pow(2,tn-1);
    for(int i=s;i<=mid;i++)
    {
        for(int j=1;j<=m;j++)
        {
            rival[tn][i][j]=mid+j;
           // printf("%d %d %d %d\n",tn,i,j,e/2+j);
        }
    }
    init(s,mid,tn-1);
    for(int i=mid+1;i<=e;i++)
    {
        for(int j=1;j<=m;j++)
        {
            rival[tn][i][j]=s+j-1;
        }
    }
    init(mid+1,e,tn-1);
}
int main()
{
    while(scanf("%d",&n),n!=-1)
    {
        memset(dp,0,sizeof(dp));
        int m=pow(2,n);
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%lf",&P[i][j]);
               // printf("%d %d %f\n",i,j,P[i][j]);
            }
        }
        init(1,m,n);
        for(int i=1;i<=m;i++)
        {
           // printf("%d %d %f\n",i,rival[1][i][1],P[i][rival[1][i][1]]);
            dp[1][i]=P[i][rival[1][i][1]];
        }
        for(int i=2;i<=n;i++)
        {
            int l=pow(2,i-1);
            for(int j=1;j<=m;j++)
            {
                for(int k=1;k<=l;k++)
                {
                   dp[i][j]+=dp[i-1][j]*dp[i-1][rival[i][j][k]]*P[j][rival[i][j][k]];
                }
            }
        }
        double ansx=0;
        int ansi=0;
        for(int i=1;i<=m;i++)
        {
            if(dp[n][i]>ansx)
            {
                //printf("%f %d\n",dp[n][i],i);
                ansx=dp[n][i];
                ansi=i;
            }
        }
        printf("%d\n",ansi);
    }
}

Football(poj3071,概率DP)

http://poj.org/problem?id=3071 Football Time Limit: 1000MS Memory Limit: 65536K Total Submissions...
  • JHC23
  • JHC23
  • 2013-08-22 21:35:26
  • 694

poj3071 概率dp

由题可知,本题为概率dp。d[i][j] 表示第i个人从第j轮晋级的概率。 则dp[i][j] = ∑〖dp[k][j-1] * p[i][k]〗* dp[i][j-1],其中k为在当前轮次所有可...
  • mosquito_zm
  • mosquito_zm
  • 2017-07-23 14:25:05
  • 79

poj3071(概率DP)

题意:淘汰赛制,2^n(n 解法:ans[i][j]表示第i个队员第j轮胜出的概率。赢到最后需要进行n场比赛。算出每个人赢到最后的ans[i][n]。写出序号的二进制发现一个规律,两个队员i...
  • xiefubao
  • xiefubao
  • 2014-05-21 12:34:29
  • 617

poj3071(概率dp)

这题题意是给出各个队伍的比赛表,哪个队伍赢的概率最高 设置状态:dp[i][j] 表示第i轮j存活的概率,那么就要找到前一轮的对手,有个小技巧貌似和二叉树有点像,在同一颗树上。 ((j >> ...
  • My_ACM_Dream
  • My_ACM_Dream
  • 2014-12-05 00:11:24
  • 246

poj3071 概率dp

传送门 题意:给定一个n,共有2^n个队伍,给出各个队伍击败另一个队的概率,求获胜的概率最大的队 思路:设dp[i][j]是第i场第j个队获胜的概率,dp[0][j]都是1,data[i][j]是i队...
  • zhubing0331
  • zhubing0331
  • 2017-08-17 13:33:16
  • 115

POJ3071 概率DP

1 归根结底是DP问题,利用概率的知识写出状态转移方程,依然是确定两件事: ①分阶段 ②递推方向和递推边界 #include #include #include using namespace...
  • a272846945
  • a272846945
  • 2016-09-07 21:05:32
  • 158

poj3071(概率DP)

地址:http://poj.org/problem?id=3071 Football Time Limit: 1000MS   Memory Limit: 65536K...
  • gaokecs1
  • gaokecs1
  • 2014-01-27 18:48:16
  • 460

poj3071之概率DP

Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2667   Accep...
  • xingyeyongheng
  • xingyeyongheng
  • 2014-05-08 21:37:11
  • 1909

LeetCode 309: 一个很清晰的DP解题思路

问题来源题目来源链接见下方: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/descript...
  • zjuPeco
  • zjuPeco
  • 2017-07-31 20:26:04
  • 320

POJ3071:Football(概率DP)

Description Consider a single-elimination football tournament involving 2n teams, denoted 1, 2, …...
  • libin56842
  • libin56842
  • 2013-08-18 23:22:37
  • 1431
收藏助手
不良信息举报
您举报文章:POJ3071题解(概率dp)
举报原因:
原因补充:

(最多只允许输入30个字)