ZOJ 10th Anniversary Contest - B Back to the Past

#include<stdio.h>

#include<string.h>

inline void swap(int & a,int & b)

{

    int k=a;

    a=b;

    b=k;

}

const int N=50;

long long binomial[N+1][N+1];

void init()

{

    int i,j;

    for (i=0;i<=N;i++)

    {

        binomial[i][0]=binomial[i][i]=1;

        for (j=1;j<i;j++)

        {

            binomial[i][j]=binomial[i-1][j-1]+binomial[i-1][j];

        }

    }

}

double p1[N+1]={1},p0[N+1]={1};

inline double oneDay(int n,int m)

{

    return binomial[n][m]*p1[m]*p0[n-m];

}

double f[N+1][N+1][N+1][N+1];

bool calc[N+1][N+1][N+1][N+1];

double getF(int n1,int m1,int n2,int m2)

{

    if (m1<0) m1=0;

    if (m2<0) m2=0;

    if (m1==0&&m2==0) return 0;

    if (n1<n2)

    {

        swap(n1,n2);

        swap(m1,m2);

    }

    double & ff=f[n1][m1][n2][m2];

    if (!calc[n1][m1][n2][m2])

    {

        ff=oneDay(n1,0)*oneDay(n2,0);

        int k1,k2;

        for (k1=0;k1<=n1;k1++) for (k2=0;k2<=n2;k2++)

        {

            if (k1==0&&k2==0) continue;

            double p=oneDay(n1,k1)*oneDay(n2,k2);

            ff+=p*(1+getF(n1-k1,m1-k1,n2-k2,m2-k2));

        }

        ff/=(1-oneDay(n1,0)*oneDay(n2,0));

        calc[n1][m1][n2][m2]=true;

    }

    return ff;

}

int main()

{

    init();

    int n,m;

    double p;

    while (1)

    {

        scanf("%d%d%lf",&n,&m,&p);

        if (n==0&&m==0&&p==0)

        {

            break;

        }

        int i;

        for (i=1;i<=n;i++)

        {

            p1[i]=p1[i-1]*p;

            p0[i]=p0[i-1]*(1-p);

        }

        memset(calc,false,sizeof(calc));

        printf("%.6f\n",(double)getF(n,m,n,m));

    }

    return 0;

}

  

你可能感兴趣的:(test)