Codeforces 540D Bad Luck Island - 概率+记忆化搜索

题意

一个岛上有三种生物A,B,C,各有多少只在输入中会告诉你,每种最多100只

A与B碰面,A会吃掉B,

B与C碰面,B会吃掉C,

C与A碰面,C会吃掉A。。。忍不住想吐槽这种环形食物链

碰面是随机的。到最后岛上只剩下一种生物,问这种生物分别是A,B,C的概率是多少。

 

【题解】

其实很简单,这题,状态方程很好想。。

设dp[i][j][k]为生物A有i只,生物B有j只,生物C有k只的概率情况,显然dp的返回值应该有三个,分别是最后剩下该种生物的概率

那么我们考虑状态转移的情况。

如果A与B碰面,概率是 p1 = i*j / (i*j+j*k+k*i),这种情况下,B会被A吃掉,所以B的数目减少1,表现出来是dp[i][j][k]= p1*dp[i][j-1][k]  (dp的3的返回值均参与计算)

B与C碰面,A与C碰面也是如此。

用全概率公式,最后的状态转移方程为 dp[i][j][k]= i*j / sum * dp[i][j-1][k] + j*k/ sum * dp[i][j][k-1] + k*i/ sum *dp[i-1][j][k]   

其中sum=i*j+j*k+k*i (满足全概率公式中的 i*j/sum 、 j*k/sum 、 k*i/sum 和为1 )

 

#include<bits/stdc++.h>

#define eps 1e-9

#define FOR(i,j,k) for(int i=j;i<=k;i++)

#define MAXN 1005

#define MAXM 40005

#define INF 0x3fffffff

#define PB push_back

#define MP make_pair

#define X first

#define Y second

#define lc (k<<1)

#define rc ((k<<1)1)

using namespace std;

typedef long long LL;

int i,j,k,n,m,x,y,T,ans,big,cas,num,len;

bool flag;

struct node

{

    double x,y,z;

    node (){}

    node (double x,double y,double z):x(x),y(y),z(z){}

}dp[105][105][105];

bool vis[105][105][105];



node dfs(int a,int b,int c)

{

    if (vis[a][b][c]) return dp[a][b][c];

    

    vis[a][b][c]=1;

    

    int sum=a*b+b*c+a*c;

    

    node r=node(0,0,0),s=node(0,0,0),t=node(0,0,0),rt;

    

    if (b>0) r=dfs(a,b-1,c); double p1=a*b*1.0/sum;

    if (c>0) s=dfs(a,b,c-1); double p2=b*c*1.0/sum;

    if (a>0) t=dfs(a-1,b,c); double p3=c*a*1.0/sum;

    

    rt.x=p1*r.x+p2*s.x+p3*t.x;

    rt.y=p1*r.y+p2*s.y+p3*t.y;

    rt.z=p1*r.z+p2*s.z+p3*t.z;

    

    return dp[a][b][c]=rt;

}



int main()

{

    int a,b,c;

    scanf("%d%d%d",&a,&b,&c);

    memset(vis,0,sizeof(vis));

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

    {

        vis[0][0][i]=1; dp[0][0][i].z=1;

        vis[0][i][0]=1; dp[0][i][0].y=1;

        vis[i][0][0]=1; dp[i][0][0].x=1;

    }

    node ans=dfs(a,b,c);

    memset(dp,-1,sizeof(dp));

    printf("%.12f %.12f %.12f\n",ans.x,ans.y,ans.z);

    return 0;

}

 

你可能感兴趣的:(codeforces)