caioj1271&&poj3071: 概率期望值2:足球

见到网上的大佬们都用了位运算。。表示看不懂就自己想了,还挺好想的(然而我不会告诉你我因为p的数组问题卡了半小时顺便D了ZZZ大佬的数据)

DP方程(伪)就是:第t轮第i个队晋级的可能=第t-1轮第i个队晋级的可能*第t-1轮第(枚举所有可以在这轮和我对战的队)队晋级的可能*战胜他的可能

所以说该怎么枚举可以在这轮和我对战的队?我们仔细研究淘汰对战表(图丑勿喷)

这里u表示在这一轮,在当前这个组里是第几个队。然后就会发现,单数组和双数组(当t=2时,3、4处于一个双数组)他要对战的队伍是不一样的,所以要分情况讨论。单数组要往下找队对战,双数组就反之。

 

 

#include<cstdio>
#include<cstring>
using namespace std;
double p[210][210],f[20][210];
int main()
{int N,n;
    while(scanf("%d",&N)!=EOF)
    {
        if(N==-1)break;
        
        n=1;for(int i=1;i<=N;i++)n*=2;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%lf",&p[i][j]);
        
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++)f[0][i]=1.0;
        int ln=1;
        for(int t=1;t<=N;t++)
        {
            int u=0,z=0;
            for(int i=1;i<=n;i++)
            {
                u++;if(u==ln+1){u=1;z=1-z;}
                if(z==0)
                {
                    int end=i-u+ln;
                    for(int j=end+1;j<=end+ln;j++)
                        f[t][i]+=f[t-1][i]*f[t-1][j]*p[i][j];
                }
                else
                {
                    int str=i-u+1;
                    for(int j=str-1;j>=str-ln;j--)
                        f[t][i]+=f[t-1][i]*f[t-1][j]*p[i][j];
                }
            }
            ln*=2;
        }
        
        int ans=0;
        double mmax=0;
        for(int i=1;i<=n;i++)
            if(f[N][i]>mmax)
            {
                mmax=f[N][i];
                ans=i;
            }
        printf("%d\n",ans);
    }
    return 0; 
}

 

posted @ 2017-09-28 19:35  AKCqhzdy  阅读(235)  评论(0编辑  收藏  举报