标签:
<p>传送门在<a target=_blank href="http://codeforces.com/contest/540/problem/D">这里</a></p><p>题意:有a、b、c三种人,其中a克b(a和b同时出现a存活b消失),b克c,c克a,初始时abc分别有x,y,z个,每次随机出两个人(可能相同种也可能不同),经过无限次之后求每种人最后存活的概率。</p><p>思路:裸的概率dp。比较通俗的想法是设dp[i][j][k]表示剩余的人中有i个a,j个b,k个c的概率,并且初始时dp[x][y][z]=1,最后只要算出sum(dp[i][0][0])就是a存活的概率。然而麻烦的是这样需要处理出来的两个人是同一种人的情况。</p><p>换一种思路,设dp[i][j][k][0]表示剩余i个a,j个b,k个c时最后a存活的概率。那么dp[i][0][0][0]=1,而dp[x][y][z][0]就是对应的a存活的概率。</p>
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
double dp[105][105][105][3];
int vis[105][105][105];
void dfs(int x,int y,int z){
//printf("%d %d %d\n",x,y,z);
if(vis[x][y][z]){
return;
}
vis[x][y][z]=1;
double sum=1.0*x*y+1.0*x*z+1.0*y*z;
double p0,p1,p2;
if(x>=1) dfs(x-1,y,z);p0=1.0*x*z/sum;
if(y>=1) dfs(x,y-1,z);p1=1.0*x*y/sum;
if(z>=1) dfs(x,y,z-1);p2=1.0*y*z/sum;
if(x>=1){
dp[x][y][z][0]+=dp[x-1][y][z][0]*p0;
dp[x][y][z][1]+=dp[x-1][y][z][1]*p0;
dp[x][y][z][2]+=dp[x-1][y][z][2]*p0;
}
if(y>=1){
dp[x][y][z][0]+=dp[x][y-1][z][0]*p1;
dp[x][y][z][1]+=dp[x][y-1][z][1]*p1;
dp[x][y][z][2]+=dp[x][y-1][z][2]*p1;
}
if(z>=1){
dp[x][y][z][0]+=dp[x][y][z-1][0]*p2;
dp[x][y][z][1]+=dp[x][y][z-1][1]*p2;
dp[x][y][z][2]+=dp[x][y][z-1][2]*p2;
}
}
int main(){
int x,y,z;
int i,j;
scanf("%d%d%d",&x,&y,&z);
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
for(i=0;i<=100;i++){
vis[i][0][0]=1;vis[0][i][0]=1;vis[0][0][i]=1;
dp[i][0][0][0]=1;
dp[0][i][0][1]=1;
dp[0][0][i][2]=1;
}
dfs(x,y,z);
printf("%.12f\n%.12f\n%.12f\n",dp[x][y][z][0],dp[x][y][z][1],dp[x][y][z][2]);
return 0;
}
标签:
原文地址:http://blog.csdn.net/u011822304/article/details/45557891