原题链接:
http://codeforces.com/contest/540/problem/D
题意:有三种人,r,s,p,其中r可以杀死s,s可以杀死p,p可以杀死r,任意时间,只要两种不同的人相遇就会杀死其中一方,已知初始r,s,p的人数,求在无限长时间以后分别只剩r,s,p类人的概率。
思路:设某一时间的人数状态为(i,j,k),则下一状态可以为(i-1,,j,k),(i,j-1,k) , (i,j,k-1),若dp[i][j][k]表示这一状态出现的概率,则以下一状态为(i-1,j,k)为例,其中任意不同类两人相遇的情况为(i*j+j*k+i*k),而i死去一个,则为i和k相遇的情况(i*k),即dp[i-1][j][k]+=dp[i][j][k]*(i*k)/(i*j+j*k+i*k)。有一些边界条件要注意,还有输出误差要求是10-9。
代码:
#include "stdio.h"
#include "iostream"
#include "string.h"
#include "stdlib.h"
#include "algorithm"
#include "math.h"
#include "map"
#include "queue"
#include "stack"
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=100005;
typedef long long LL;
int a,b,c;
double dp[101][101][101];
int cc[3][3]={-1,0,0,0,-1,0,0,0,-1};
void getdp(int i,int j,int k,int w)
{
double s=i*j+j*k+i*k;
int a1,a2,a3;
a1=i+cc[w][0];
a2=j+cc[w][1];
a3=k+cc[w][2];
if(a1<0||a2<0||a3<0||a1+a2+a3<=0||s==0)
return;
if(w==0)
{
dp[a1][a2][a3]+=dp[i][j][k]*(i*k)/s;
}
else if(w==1)
{
dp[a1][a2][a3]+=dp[i][j][k]*(i*j)/s;
}
else
{
dp[a1][a2][a3]+=dp[i][j][k]*(j*k)/s;
}
}
int main()
{
memset(dp,0,sizeof(dp));
scanf("%d%d%d",&a,&b,&c);
dp[a][b][c]=1;
double ans1=0,ans2=0,ans3=0;
for(int i=a;i>=0;i--)
{
for(int j=b;j>=0;j--)
{
for(int w=c;w>=0;w--)
{
for(int q=0;q<3;q++)
{
getdp(i,j,w,q);
}
}
}
}
for(int i=1;i<=a;i++)
ans1+=dp[i][0][0];
for(int i=1;i<=b;i++)
ans2+=dp[0][i][0];
for(int i=1;i<=c;i++)
ans3+=dp[0][0][i];
printf("%.10lf %.10lf %.10lf\n",ans1,ans2,ans3);
return 0;
}