codeforces 540D D. Bad Luck Island( 概率dp)

题目链接:

codeforces 540D

题目大意:

会出石头、剪刀、布的人分别有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 );
    }
}

你可能感兴趣的:(dp,概率,codeforces)