题目描述
传送门
题意:
2^n个队进行足球赛,每个队打败另外一个队都有一个概率。
比赛一共进行n轮,每轮相邻的两只球队比赛,负者淘汰
问最后胜利的概率最大的是哪只球队
题解
概率dp
令f(i,j)表示第i轮第j支球队获胜的概率
那么
f(i,j)=∑kf(i−1,j)∗f(i−1,k)∗p(j,k)
,其中k需要取遍这一轮所有有可能与j比赛的球队
感觉这题难不在dp,而在处理那棵二叉树啊。。。
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int n,champion,mi[10];
double p[200][200],f[10][200],Max;
void clear()
{
champion=0;Max=0;
memset(f,0,sizeof(f));
memset(p,0,sizeof(p));
}
int main()
{
while (~scanf("%d",&n))
{
if (n==-1) break;
clear();
mi[0]=1;for (int i=1;i<=n;++i) mi[i]=mi[i-1]*2;
for (int i=1;i<=mi[n];++i)
for (int j=1;j<=mi[n];++j)
scanf("%lf",&p[i][j]);
for (int i=1;i<=mi[n];++i) f[0][i]=1.0;
for (int i=1;i<=n;++i)
for (int j=1;j<=mi[n];++j)
{
int l=(j-1)/mi[i]*mi[i]+1,r=((j-1)/mi[i]+1)*mi[i];
if (j>(l+r)/2) r=(l+r)/2;
else l=(l+r)/2+1;
for (int k=l;k<=r;++k)
f[i][j]+=f[i-1][k]*f[i-1][j]*p[j][k];
}
champion=1;Max=f[n][1];
for (int i=2;i<=mi[n];++i)
if (f[n][i]>Max)
{
Max=f[n][i];
champion=i;
}
printf("%d\n",champion);
}
}