题目描述
淘汰赛制是一种极其残酷的比赛制度。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)
分析:
一道较为有思考难度的DP,通过考虑每次原位置的变化进行DP即可。
CODE:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 using namespace std; 7 const int M=2005; 8 const double esp=0.000001; 9 const double hyh=0.999; 10 double f[M][15]; 11 int win[M][M]; 12 int n; 13 int get(){ 14 char c=getchar(); 15 int res=0,f=1; 16 while (c>'9'||c<'0'){ 17 if (c=='-') f=-1; 18 c=getchar(); 19 } 20 while (c<='9'&&c>='0'){ 21 res=(res<<3)+(res<<1)+c-'0'; 22 c=getchar(); 23 } 24 return res*f; 25 } 26 double maxn; 27 int pos; 28 int main(){ 29 n=get(); 30 long long m=(1<<n); 31 for (int i=1;i<=m;i++) 32 for (int j=1;j<=m;j++) 33 win[i][j]=get(); 34 for (int i=1;i<=m;i++) f[i][0]=1; 35 for (int i=1;i<=n;i++){ 36 for (int j=1;j<=m;j++){ 37 int posi=(int)(j*1.0/(1<<(i-1))+hyh); 38 //int posi=ceil((double)j/(1<<(i-1))); 39 int posx=(posi&1)?posi+1:posi-1; 40 for (int k=posx*(1<<(i-1))-(1<<(i-1))+1;k<=posx*(1<<(i-1));k++) 41 f[j][i]+=f[j][i-1]*win[j][k]/100*f[k][i-1]; 42 //cout<<f[j][i]<<endl; 43 } 44 } 45 for (int i=1;i<=m;i++){ 46 if (f[i][n]>maxn+esp) maxn=f[i][n],pos=i; 47 //cout<<f[i][n]<<endl; 48 } 49 cout<<pos<<endl; 50 return 0; 51 }