BUPT Summer Journey #test8 D

来源:互联网 发布:工业废气排放总量数据 编辑:程序博客网 时间:2024/05/06 19:04

 

D. 解码锦标赛 2014新生暑假个人排位赛08

时间限制 1000 ms    内存限制65536 KB    

题目描述

明光村迎来了一年一度的盛世——解码锦标赛,有 2^N 次个队伍从世界各村赶来参与比赛,编号为 1 - 2^N。赛制为每一轮晋级一半队伍,按序号大小两两比赛,淘汰弱者。一轮结束后,所有的胜者进入下一轮,依旧是按顺序两两比赛。比如第一轮就是 1 vs 2, 3 vs 4 ... 2^N - 1 vs 2^N。在一旁围观的 Mays 学姐告诉你,N次比赛后的胜者是唯一的。现在你拿到了一份各个参赛队伍的对抗胜率表 win,为 2^N * 2^N 的矩阵, win[i][j] 为一位小数,代表i胜j的概率。 

你能告诉 Mays 学姐最有可能获得世界冠军的是那支队伍吗?

输入格式

多组数据。每组第一行为 N ,N <= 8,接下来 N 行 N 列为对抗胜率矩阵。 保证 win[i][j] + win[j][i] = 1 (i != j)。 以 N=0 结束输入。 

输出格式

对每组数据,输出胜率最大的队伍的序号。如果最大的两个概率相差不到 0.001,则认为胜率相等,输出序号最小者。

输入样例

20.0 0.1 0.2 0.30.9 0.0 0.4 0.50.8 0.6 0.0 0.60.7 0.5 0.4 0.020.0 0.8 0.1 0.4 0.2 0.0 0.2 0.6 0.9 0.8 0.0 0.3 0.6 0.4 0.7 0.0 0

输出样例

24

 

思路:其实用dp[i][j]表示i个人第一轮比赛获胜的概率,则每一次递推则等于它与另一组的每一个人出线的概率与i获胜的概率乘积的累加。然后注意区间处理即可。

代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>//#define LOCALusing namespace std;int n;double p[1000][1000];double dp[1000][1000];int main(){    #ifdef LOCAL    freopen("input.txt","r",stdin);    #endif // LOCAL    while(scanf("%d",&n)==1&&n)    {        for(int i=0;i<(1<<n);i++)            for(int j=0;j<(1<<n);j++)scanf("%lf",&p[i][j]);        for(int i=0;i<(1<<n);i++)dp[i][1]=p[i][i^1];        //for(int i=0;i<(1<<n);i++)printf("ans[%d]=%lf\n",i,dp[i][1]);        for(int h=1;h<n;h++)            for(int i=0;i<(1<<n);i++)            {                double temp=0.0;                //printf("i=%d\n",i);                for(int j=0;j<(1<<h);j++)temp=temp+dp[((i/(1<<h))^1)*(1<<h)+j][h]*p[i][((i/(1<<h))^1)*(1<<h)+j];                //printf("%lf\n",temp);                dp[i][h+1]=dp[i][h]*temp;//printf("%d ",((i/(1<<h))^1)*(1<<h)+j);            }        //for(int i=0;i<(1<<n);i++)printf("ans[%d]=%lf\n",i,dp[i][n]);        //for(int i=0;i<(1<<n);i++)printf("ans[%d]=%lf\n",i,ans[i]);        int maxx=0;        for(int i=1;i<(1<<n);i++)if(dp[i][n]>dp[maxx][n])maxx=i;        printf("%d\n",maxx+1);    }    return 0;}


 

0 0
原创粉丝点击