codeforces 148D D. Bag of mice(概率dp)

题目链接:

codeforces 148D

题目大意:

给出w只白老鼠,b只黑老鼠,公主和龙轮流取老鼠,公主先手,龙取老鼠时会吓跑一只老鼠,先取出白老鼠的人赢,如果没人取到白老鼠,那么龙赢。问公主赢的概率。

题目分析:

  • 首先定义状态dp[i][j]表示第i次取老鼠时剩余黑老鼠为j的概率。
  • 那么最后结果就是
    ij=0bdp[i][j]
  • 那么怎么转移呢?分两种情况
    • i&1 :
      dp[i][j]=dp[i1][j+1]j+1sumi1
    • else:
      dp[i][j]=dp[i1][j+1](j+1)(sumi1j1)sumi1sumi11
  • 然后就是注意边界情况了,因为double值在边界情况上会出现很多情况,具体特判见代码

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAX 1007

using namespace std;

double dp[MAX][MAX];
int w,b,sum;

void calc ( int x )
{
    sum = x+x/2;
    sum = w+b-sum;
}

int main ( )
{
    while ( ~scanf ( "%d%d" , &w , &b ) )
    {
        if ( w == 0 )
        {
            puts ("0.0000000000" );
            continue;
        }
        memset ( dp , 0 ,sizeof ( dp ) );
        dp[0][b] = 1.0;
        for ( int i = 1 ; i <= b; i++ )
        {
            calc ( i-1 );
            for ( int j = 0; j <= b ; j++ )
            {
                dp[i][j] = 0;
                if ( i&1 )
                    dp[i][j] = dp[i-1][j+1]*((j+1)*1.0/(sum*1.0));
                else 
                {
                    double x = (j+1)*(j+2)*1.0/(sum*(sum-1)*1.0);
                    dp[i][j] += dp[i-1][j+2]*x;
                    x = (j+1)*(sum-1-j)*1.0/(sum*(sum-1)*1.0);
                    dp[i][j] += dp[i-1][j+1]*x;
                }
            }
        }
        double ans = 0;
        for ( int i = 0 ; i <= b ; i += 2 )
            for ( int j = 0 ; j <= b ; j++ )
            {
                calc ( i );
                if ( sum == 0 || sum < j  ) continue;
                //cout << dp[i][j] << " " << ans << endl;
                ans += dp[i][j]*((sum-j) *1.0/(sum*1.0));
            }
        printf ( "%.10lf\n" , ans );
    }
}

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