POJ 3071 Football【概率DP】

題目鏈接

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

思路

概率DP,方程本身很簡單,設dp[i][j]爲第i支隊伍撐過第j輪的概率。
則對第j輪i所有的可能對手k,dp[i][j]+=dp[i][j-1]*dp[k][j-1]*p[i][k]

但是難點就是怎麼找出可能對手k,上網搜了下發現可以巧妙的用二進制搞定。

把ijk都從0開始編號,那麼在第j輪,i和k可能是對手當且僅當i和k的第(j+1)位相反且最高位相同。
即:((k>>j)^1)==(i>>j)

AC代碼

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;


double dp[200][10];
double p[200][200];
int main()
{
    int n;
    while(scanf("%d",&n),n!=-1)
    {
        int n_team=(1<<n);
        for(int i=0 ; i<n_team ; ++i)
            for(int j=0 ; j<n_team ; ++j)
                scanf("%lf",&p[i][j]);
        memset(dp,0,sizeof dp);
        for(int i=0 ; i<n_team ; i+=2)
        {
            dp[i][0]=p[i][i+1];
            dp[i+1][0]=p[i+1][i];
        }
        for(int j=1 ; j<n ; ++j)
        {
            for(int i=0 ; i<n_team ; ++i)
            {
                for(int k=0 ; k<n_team ; ++k)
                if(((k>>j)^1)==(i>>j))
                {
                    dp[i][j]+=dp[i][j-1]*dp[k][j-1]*p[i][k];
                }
            }
        }
        double max_p=dp[0][n-1];
        int max_i=0;
        for(int i=1 ; i<n_team ; ++i)
        {
            if(dp[i][n-1]>max_p)
            {
                max_p=dp[i][n-1];
                max_i=i;
            }
        }
        printf("%d\n",max_i+1);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章