zoukankan      html  css  js  c++  java
  • [POJ 3071]Football[概率DP]

    [POJ 3071]Football[概率DP]

    题目大意

    (2^n) 个编号为 (1, 2, 3, ldots, 2^n) 的队伍进行足球比赛,一开始 (1)(2) 打,(3)(4) 打... 赢得队伍按照原来的相对顺序重新编号 (1, 2, ldots, 2^{n-1}),按上规则进行比赛。给出一个胜率的概率矩阵,求最终最可能获胜的队伍。

    数据范围:多组数据,(n leq 7)

    解题方法

    (f[i][j]) 表示进行 (i) 场比赛,(j) 获胜的概率,可以得到转移方程:

    [f[i][j] = sum f[i - 1][j] imes f[i-1][t] imes p[j][t] ]

    其中 (t) 是在第 (i) 场比赛中可能与 (j) 交手的队伍,现在问题关键在于如何求解 (t)

    一开始的队伍 (1, 2, ldots, 2^n) 可以被分为 (2^{n-1}) 组,每个队可能和一个队打,容易发现第 (i) 场时 (j) 的对手可能有 (2^{i-1}) 个,整个 (1,2,ldots,2^n) 可以被分为 (2^{n-i}) 组。所以只要知道当前 (j) 在第几组即可,可以知道在第

    [frac{j-1}{2^{i-1}} + 1 ]

    组。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 257;
    double p[N][N], dp[N][N];
    int n;
    
    int main() {
        while(true) {
            scanf("%d", &n);
            if(n < 0) break;
            for(int i = 1; i <= (1 << n); i++)
                for(int j = 1; j <= (1 << n); j++) scanf("%lf", &p[i][j]);
            memset(dp, 0, sizeof dp);
            for(int i = 1; i <= (1 << n); i++) dp[0][i] = 1;
            for(int i = 1; i <= n; i++) {
                for(int j = 1; j <= (1 << n); j++) {
                    int cur = (j - 1) / (1 << (i - 1));
                    if(cur & 1) {
                        for(int t = (cur - 1) * (1 << (i - 1)) + 1; t <= cur * (1 << (i - 1)); t++) {
                            dp[i][j] += dp[i - 1][j] * dp[i - 1][t] * p[j][t];
                        }
                    } else {
                        for(int t = (cur + 1) * (1 << (i - 1)) + 1; t <= (cur + 2) * (1 << (i - 1)); t++) {
                            dp[i][j] += dp[i - 1][j] * dp[i - 1][t] * p[j][t];
                        }
                    }
                }
            }
            double pWin = dp[n][1]; int winner = 1;
            for(int i = 2; i <= (1 << n); i++) {
                if(pWin < dp[n][i]) pWin = dp[n][i], winner = i;
            }
            printf("%d
    ", winner);
        }
        return 0;
    }
    
  • 相关阅读:
    ES head安装笔记, 还没有试
    sed用法笔记
    Kibana笔记
    ElasticSearch笔记
    Mongo聚合笔记
    java 判断是否为数字
    Redis 一:安装篇
    make问题:make[1] entering directory
    Java 多线程 简单实例 (消费者与生成者)的关系
    Java 多线程 简单实例 (Runnable)
  • 原文地址:https://www.cnblogs.com/_inx/p/13538116.html
Copyright © 2011-2022 走看看