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

时间:2023-12-23 22:07:49

题意

一个岛上有三种生物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[][][];
bool vis[][][]; node dfs(int a,int b,int c)
{
if (vis[a][b][c]) return dp[a][b][c]; vis[a][b][c]=; int sum=a*b+b*c+a*c; node r=node(,,),s=node(,,),t=node(,,),rt; if (b>) r=dfs(a,b-,c); double p1=a*b*1.0/sum;
if (c>) s=dfs(a,b,c-); double p2=b*c*1.0/sum;
if (a>) t=dfs(a-,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,,sizeof(vis));
for (i=;i<=;i++)
{
vis[][][i]=; dp[][][i].z=;
vis[][i][]=; dp[][i][].y=;
vis[i][][]=; dp[i][][].x=;
}
node ans=dfs(a,b,c);
memset(dp,-,sizeof(dp));
printf("%.12f %.12f %.12f\n",ans.x,ans.y,ans.z);
return ;
}