原題鏈接:
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;
}