• POJ 3071 Football:概率dp


    题目链接:http://poj.org/problem?id=3071

    题意:

      给定n,有2^n支队伍参加足球赛。

      给你所有的p[i][j],表示队伍i打败队伍j的概率。

      淘汰赛制。第一轮(1,2)两队比、(3,4)比、(5,6)比...共进行n轮比赛后产生冠军。

      问你冠军最有可能是哪支队伍。

    题解:

      表示状态:

        dp[i][j] = probability to win

        第i支队伍能够参加第j轮比赛的概率。

      找出答案:

        i of max dp[i][n+1]

        n轮比赛后,冠军该参加第n+1轮比赛(不存在的)。

      如何转移:

        now: dp[i][j]

        dp[i][j+1] = ∑ (dp[i][j] * dp[k][j] * p[i][k]) (加法原理)

        k: 第j轮比赛和i比的队伍

        P(i晋级到j+1轮) = ∑ (P(i晋级到j轮) * P(k晋级到j轮) * P(i打败k))

        怎样枚举k:

          将所有队伍从0开始编号,并用二进制表示。

          第i支战队第j轮会碰到的对手是:将i化为二进制,从右往左开始算,第j-1位会不同,第j位开始要相同,其余位任意的所有数。

      边界条件:

        dp[i][1] = 1
        others = 0

      注:本题居然卡cin。。。 (*`皿´*)ノ 

    AC Code:

     1 // state expression:
     2 // dp[i][j] = probability to win
     3 // i: which team
     4 // j: which round
     5 //
     6 // find the answer:
     7 // i of max dp[i][n+1]
     8 //
     9 // transferring:
    10 // dp[i][j+1] = sigma (dp[i][j] * dp[k][j] * p[i][k])
    11 // 0<=t<(1<<(j-1))
    12 // k = (((i>>(j-1))^1)<<(j-1))|t
    13 //
    14 // boundary:
    15 // dp[i][1] = 1
    16 #include <iostream>
    17 #include <stdio.h>
    18 #include <string.h>
    19 #define MAX_N 10
    20 #define MAX_T 150
    21 
    22 using namespace std;
    23 
    24 int n;
    25 int ans;
    26 double p[MAX_T][MAX_T];
    27 double dp[MAX_T][MAX_N];
    28 
    29 void read()
    30 {
    31     for(int i=0;i<(1<<n);i++)
    32     {
    33         for(int j=0;j<(1<<n);j++)
    34         {
    35             scanf("%lf",&p[i][j]);
    36         }
    37     }
    38 }
    39 
    40 void solve()
    41 {
    42     memset(dp,0,sizeof(dp));
    43     for(int i=0;i<(1<<n);i++)
    44     {
    45         dp[i][1]=1;
    46     }
    47     for(int j=1;j<=n;j++)
    48     {
    49         for(int i=0;i<(1<<n);i++)
    50         {
    51             for(int t=0;t<(1<<(j-1));t++)
    52             {
    53                 int k=((((i>>(j-1))^1)<<(j-1))|t);
    54                 dp[i][j+1]+=dp[i][j]*dp[k][j]*p[i][k];
    55             }
    56         }
    57     }
    58     double maxn=0;
    59     for(int i=0;i<(1<<n);i++)
    60     {
    61         if(dp[i][n+1]>maxn)
    62         {
    63             maxn=dp[i][n+1];
    64             ans=i+1;
    65         }
    66     }
    67 }
    68 
    69 void print()
    70 {
    71     printf("%d
    ",ans);
    72 }
    73 
    74 int main()
    75 {
    76     while(scanf("%d",&n)!=EOF)
    77     {
    78         if(n==-1) break;
    79         read();
    80         solve();
    81         print();
    82     }
    83 }
  • 相关阅读:
    !!“理都懂”为什么“然并卵”?
    启明创投甘剑平:破解独角兽公司的基因密码
    任正非:华为3年前应该快垮了
    C语言 · 8皇后问题改编
    C语言 · 数的划分
    C语言 · 8皇后问题
    C语言 · 数字黑洞
    C语言 · FBI树
    C语言 · 超级玛丽
    C语言 · 数的划分
  • 原文地址:https://www.cnblogs.com/Leohh/p/7467312.html
Copyright © 2020-2023  润新知