poj 3071 Football

http://poj.org/problem?id=3071

 记忆化搜索

代码及其注释:

#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cstring>

#include<cmath>

#include<map>

#include<cmath>

#define LL long long



using namespace std;



const int N=130;



double win[N][N];//第几队 在第几次比赛中获胜的概率

double beat[N][N];// i赢j的概率

double pro(int k,int x,int l,int r)//第k队 第x次比赛 l和r用来确认范围

{

    if(win[k][x]>=0.0)

    return win[k][x];//记忆化

    if(x==0)

    {

        win[k][x]=1.0;//第0次一定获胜 为边界

        return win[k][x];

    }

    int mid=(l+r)>>1;

    double ftemp=0.0;

    if(k<=mid)//判定k 所在的范围 和他的对手范围

    {

        for(int i=mid+1;i<=r;++i)

        {

            ftemp+=(beat[k][i]*pro(i,x-1,mid+1,r));//累加  对手出现的概率和打败概率的乘积

        }

        win[k][x]=pro(k,x-1,l,mid)*ftemp;//最后乘上自己出现的概率

    }else

    {

        for(int i=l;i<=mid;++i)

        {

            ftemp+=(beat[k][i]*pro(i,x-1,l,mid));

        }

        win[k][x]=pro(k,x-1,mid+1,r)*ftemp;

    }

    return win[k][x];

}

int main()

{

    int n;

    while(scanf("%d",&n)!=EOF)

    {

        if(n==-1)

        break;

        int m=int(pow(2,n));

        for(int i=1;i<=m;++i)

        {

            for(int j=1;j<=m;++j)

            {

                scanf("%lf",&beat[i][j]);

            }

        }

        for(int i=1;i<=m;++i)

        {

            for(int j=0;j<=n;++j)

            {

                win[i][j]=-1.0;//初始化

            }

        }

        int ans=1;

        for(int i=1;i<=m;++i)

        {

            if(pro(i,n,1,m)>win[ans][n])//枚举每队的获胜概率 记录最大的队伍

            ans=i;

        }

        printf("%d\n",ans);

    }

    return 0;

}

  

你可能感兴趣的:(poj)