[NOI导刊] [2010] [提高] 淘汰赛制

[NOI导刊] [2010] [提高] 淘汰赛制


题目:

题目描述

淘汰赛制是一种极其残酷的比赛制度。\(2n\)名选手分别标号\(1,2,3,…,2^{n}-1,2^{n}\),他们将要参加\(n\)轮的激烈角逐。每一轮中,将所有参加该轮的选手按标号从小到大排序后,第\(1\)位与第\(2\)位比赛,第\(3\)位与第\(4\)位比赛,第\(5\)位与第\(6\)位比赛……只有每场比赛的胜者才有机会参加下一轮的比赛(不会有平局)。这样,每轮将淘汰一半的选手。\(n\)轮过后,只剩下一名选手,该选手即为最终的冠军。现在已知每位选手分别与其他选手比赛获胜的概率,请你预测一下谁夺冠的概率最大。

输入输出格式

输入格式:

第一行是一个整数\(n(l \leqslant n \leqslant 10)\),表示总轮数。接下来\(2^{n}\)行,每行\(2^{n}\)个整数,第\(i\)行第\(j\)个是\(P_{i j}(0≤P_{i j}≤100,P_{ii}=0,P_{i j}+P_{j i}=100)\),表示第\(i\)号选手与第\(j\)号选手比赛获胜的概率。

输出格式:只有一个整数\(c\),表示夺冠概率最大的选手编号(若有多位选手,输出编号最小者)。

输入输出样例

输入样例#1:

  2
  0 90 50 50
  10 0 10 10
  50 90 0 50
  50 90 50 0

输出样例#1:

 1

说明

\(30%\)的数据满足\(n \leqslant 3\)\(100%\)的数据满足\(n \leqslant 10\)

题解:

为表达简洁,我还是设几个值吧:

\(p[i][j]\)\(j\)号选手第\(i\)轮晋级的概率;\(m[i][j]\)\(i\)\(j\)比赛的胜利概率。

分组,每一轮求出有可能与\(i\)进行比赛的选手。设\(l\)\(r\)为有可能与\(i\)比赛选手的序列的左区间与右区间,\(q\)为当前比赛轮数,求\(sum = \sum_{k = l}^{r} p[q - 1][k] * m[i][k]\)\(p[q][i]\)即为\(p[q - 1][i] * sum\)

#include <cstdio>
const int MAXN = 1100;
const double EPS = 1e-6;
int m[MAXN][MAXN];
double p[12][MAXN];
int n, tn, ansi;
int main() {
    scanf("%d", &n);
    tn = 1 << n;
    for (int i = 1; i <= tn; ++i)
        for (int j = 1; j <= tn; ++j)
            scanf("%d", &m[i][j]);
    for (int i = 1; i <= tn; ++i) p[0][i] = 1.0;
    for (int i = 1; i <= n; ++i) {
        int rnum = 1 << (i - 1);
        for (int j = 1; j <= tn; ++j) {
            int numt(0), numc(0);
            numt = (j - 1) / rnum + 1;
            numc = (numt & 1) ? numt + 1 : numt - 1;
            int rangex = rnum * numc; double sum(0);
            for (int k = rnum * (numc - 1) + 1; k <= rangex; ++k)
                sum = sum + p[i - 1][k] * m[j][k] * 0.01;
            p[i][j] = p[i - 1][j] * sum;
        }
    }
    ansi = 1;
    for (int i = 2; i <= tn; ++i)
        if(p[n][i] - p[n][ansi] > EPS) ansi = i;
    printf("%d\n", ansi);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/manziqi/p/9205060.html