POJ_3071 Football 概率dp

来源:互联网 发布:怎么解析json 编辑:程序博客网 时间:2024/06/10 19:45

http://poj.org/problem?id=3071

题意:

有(1<<N)个人进行N次比赛,每次比赛都是第i个人和第i+1个人进行,赢的人能进入下一轮,输的人就不能继续比赛,N轮比赛之后,只会有一个人留下来,问谁最终留下来的概率最大。

思路:

概率dp,我们用dp[i][j]表示经过i场比赛之后,第j个人还没被淘汰的概率,那么状态转移方程就变成了:

dp[i][j] = sum{ dp[i-1][j] * dp[i-1][k] * P[j][k] } ,其中的k表示在第i轮有机会和i比赛的人的编号,P[j][k]表示jbeatsk的概率,最后只需要比较谁的概率最大就可以了。

代码:

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#define STOP() system("pause")const int MAXN = 150 ;int N , NN;double P[MAXN][MAXN] ;double dp[10][MAXN];void solve(){    for(int i=1;i<=NN;i++)        dp[0][i] = 1 ;    for(int i=1;i<=N;i++){        int aa = 1 << (i-1) ;        for(int j=1;j<=NN;j++){            int s , e  ;            s = 0  ;            int cnt = 0 ;            while( s + aa < j )   s += aa ,cnt ++ ;            if( (cnt & 1) == 0 ){                s += aa ;                e = s + aa ; s = s + 1 ;            }            else{                e = s ;                s = s - aa  + 1 ;            }            dp[i][j] = 0 ;            for(int k=s;k<=NN && k<=e;k++){                dp[i][j] += dp[i-1][j] * dp[i-1][k] * P[j][k] ;            }        }    }    double _max = 0 ;    int max_num ;    for(int i=1;i<=NN;i++){        if( dp[N][i] > _max ){            _max = dp[N][i] ;            max_num = i ;        }    }    printf("%d\n",max_num);}int main(){    while( scanf("%d",&N)==1){        if(N == -1) break;        NN = 1 << N ;        for(int i=1;i<=NN;i++){            for(int j=1;j<=NN;j++)                scanf("%lf",&P[i][j]);        }        solve() ;    }    return 0 ;}



原创粉丝点击