洛谷 P1769 淘汰赛制_NOI导刊2010提高(01) P1769 淘汰赛制_NOI导刊2010提高(01)

题目描述

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

现在已知每位选手分别与其他选手比赛获胜的概率,请你预测一下谁夺冠的概率最大。

输入输出格式

输入格式:

 

输入文件elimination.in。第一行是一个整数n(l≤n≤l0),表示总轮数。接下来2^n行,每行2^n个整数,第i行第j个是Pij(0≤pij≤100,Pii=0,Pij+Pji=100),表示第i号选手与第j号选手比赛获胜的概率。

 

输出格式:

 

输出文件elimination.out。只有一个整数c,表示夺冠概率最大的选手编号(若有多位选手,输出编号最小者)。

 

输入输出样例

输入样例#1:
  2
  0 90 50 50
  10 0 10 10
  50 90 0 50
  50 90 50 0
输出样例#1:
 1

说明

30%的数据满足n≤3;100%的数据满足n≤10。

_NOI导刊2010提高(01)

思路:

对于样例,我们可以模拟一下:

1号选手通过第1轮(进入决赛)的概率为90%,即击败2号选手的概率。同理,2号选手通过第1轮的概率为10%,3号,4号选手都是50%。

对于3号选手通过第2轮(通过第n轮夺冠)的概率,我们可以分情况讨论。假设3号选手已经通过第1轮。如果1号选手通过第1轮(90%的可能性),则3号选手通过第2轮的概率为50%,即击败1号选手的概率,所以3号选手击败1号选手通过第2轮的概率为90%*50%=45%;如果2号选手通过第1轮(10%的可能性),则3号选手通过第2轮的概率为90%,即击败2号选手的概率,所以3号选手击败2号选手通过第2轮的概率为10%*90%=9%。所以3号选手击败对手通过第2轮的概率为45%+9%=54%,而这是在3号选手已经通过第1轮的基础上的概率,自然,3号选手最初时通过第2轮的概率只有50%*54%=27%。

同理,4号选手最初时通过第2轮的概率为27%,1号选手通过第2轮的概率为45%,2号选手为1%,45%>27%>27%>1%,所以答案输出1。

所以:每一位选手通过这一轮的概率为这一位选手通过上一轮的概率乘上这一位选手击败这一轮遇到的每一个对手的概率之和

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,num;
double maxn=-100;
double map[1030][1030];
double f[1030],ff[1030];
int main(){
    scanf("%d",&n);
    num=pow(2,n);
    for(int i=1;i<=num;i++)
        for(int j=1;j<=num;j++){
            int x;
            scanf("%d",&x);
            map[i][j]=x*1.0/100*1.0;
        }
    for(int i=1;i<=num;i++)
        if(i%2==0)    f[i]=map[i][i-1];
        else f[i]=map[i][i+1];
    for(int i=2;i<=n;i++){
        for(int j=1;j<=num;j++){
            double bns=0;
            int l,r,aa=pow(2,i-1),tmp=(j-1)/aa;
            if(tmp%2==0){    l=aa*(tmp+1)+1;    r=aa*(tmp+2);    }
            else{    l=aa*(tmp-1)+1;    r=aa*tmp;    }
            for(int k=l;k<=r;k++)
                bns+=f[k]*map[j][k];
            ff[j]=f[j]*bns;
        }
        for(int j=1;j<=num;j++)
            f[j]=ff[j];
    }
    int ans;
    for(int i=1;i<=num;i++)
        if(f[i]>maxn){
            ans=i;
            maxn=f[i];
        }
    cout<<ans;
}