标签:
<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