题目链接:
题目大意:
会出石头、剪刀、布的人分别有r,s,p个,他们相互碰到的概率相同,输的人死掉,问最终活下去的人是三种类型的概率。
题目分析:
- 我们定义dp[i][j][k]三维分别表示三种人剩余的个数,数组记录的值是当前这个状态出现的概率。
- 那么dp[r][s][p]=1.0,这就是动态规划的初始状态。
- 我们容易想到:设dp[i+1][j][k]转移到dp[i][j][k]的概率是
p
,定义sum=i*j+j*k+k*i,那么
pi=(i+1)∗jsum - 那么我们就得到如下的转移方程:
dp[i][j][k]=dp[i+1][j][k]⋅pi+dp[i][j+1][k]⋅pj+dp[i][j][k+1]⋅pk
- 最终我们统计每种导致各种类型的人必胜的局势的概率,输出结果即可。
AC代码:
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAX 107
using namespace std;
double dp[MAX][MAX][MAX];
int r,s,p;
int main ()
{
while (~scanf("%d%d%d" , &r , &s , &p ))
{
memset ( dp , 0 , sizeof ( dp ));
dp[r][s][p] = 1.0;
for ( int i = r ; i >= 1 ; i-- )
for ( int j = s ; j >= 1 ; j-- )
for ( int k = p ; k >= 1 ; k-- )
{
double sum = i*j+j*k+k*i;
dp[i-1][j][k] += dp[i][j][k]*(i*k*1.0/sum);
dp[i][j-1][k] += dp[i][j][k]*(j*i*1.0/sum);
dp[i][j][k-1] += dp[i][j][k]*(j*k*1.0/sum);
/*cout << dp[1][1][0] << endl;
cout << dp[2][2][0] << endl;
cout << dp[1][2][0] << endl;
cout << dp[2][1][0] << endl;*/
}
double ans1,ans2,ans3;
ans1 = ans2 = ans3 = 0.0;
for ( int i = 1 ; i <= 100 ; i++ )
for ( int j = 0 ; j <= 100 ; j++ )
{
ans1 += dp[i][j][0];
ans2 += dp[0][i][j];
ans3 += dp[j][0][i];
}
printf ( "%.10f %.10f %.10f\n" , ans1 , ans2 , ans3 );
}
}