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;
}

 

转载于:https://www.cnblogs.com/zhyfzy/p/4471091.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值