URAL 1994 The Emperor's plan 概率dp

题目大意:

现在有n个参议员,其中有k个人是 Palpatine 安插在其中的间谍,为了谋取自己的利益,现在 Palpatine 安插在参议员中的间谍在每个晚上都会干掉不是间谍的参议员,一个间谍一天晚上只会干掉一个参议员,且间谍在晚上不会干掉自己人,在白天的时候,为了排除间谍,参议员们要排挤掉一部分人使得剩下的不是间谍的参议员的人数期望值最大,白天排挤一部分人出去的时候是随机的 (相当于白天间谍互相不认识) ,只是数量决定于排挤之后剩余的非间谍参议员的人数期望,那么这样子持续下去,多天之后只剩下全是间谍的参议员或者全不是间谍的参议员之后结束,问最终剩下的不是间谍的参议员的人数的期望值


大致思路:

用 f ( x, y ) 表示进入下一个晚上时剩下 x 个非间谍和 y 个间谍的时候最终剩下的非间谍人数的期望,那么显然有:

f ( x <= y) = 0 (当晚非间谍全部被杀死)  f ( x , 0 ) = x ( 间谍被排挤完了)

最终需要的结果是 f ( n -  k, k )

其他时候,由于进入晚上,非间谍将剩下 x - y个,这样在白天的时候剩下x - y个非间谍, y 个间谍, 假设排挤掉 i 个人,那么排挤掉 i 个人中假设有 j 个是非间谍, i - j个是间谍,那么可以排列组合算出这种情况下的期望,对于 i 可以是 0 到 x, j 可以是 0到min(i, x)算出每种 i 下的期望值取最大递归即可

细节见代码:

Result  :  Accepted     Memory  :  1329 KB     Time  :  250 ms

/*
 * Author: Gatevin
 * Created Time:  2014/8/13 18:58:54
 * File Name: haha.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

double C[250][250];
double dp[250][250];

void initial()
{
    C[0][0] = 1;
    for(int i = 1; i <= 249; i++)
    {
        for(int j = 0; j <= i; j++)
        {
            C[i][j] = j == 0 ? 1 : C[i - 1][j] + C[i - 1][j - 1];
        }
    }
    for(int i = 1; i <= 249; i++) for(int j = 1; j <= 50; j++) dp[i][j] = -1;
    return;
}

double f(int x, int y)
{
    if( x <= y) return 0;
    if( y == 0) return x;
    if(dp[x][y] > -0.5) return dp[x][y];//记忆化搜索,如果已经计算过直接返回
    double ret = 0;
    x -= y;
    double tmp = 0;
    for(int i = 0; i <= x + y; i++)//枚举白天可能的排挤掉的人数
    {
        tmp = 0;
        for(int j = 0; j <= min(i, x); j++)//j为白天排挤掉的人中非间谍的人数
        {
            tmp += C[x][j] / C[x + y][i] * C[y][i - j] * f(x - j, y - i + j);
        }
        ret = max(ret, tmp);//取最大的情况
    }
    dp[x + y][y] = ret;//记录计算过的答案
    return ret;
}

int main()
{
    int n,k;
    cin>>n>>k;
    initial();
    printf("%.6lf\n", f(n - k, k));
    return 0;
}


你可能感兴趣的:(dp,plan,the,Probability,1994,ural,ural,Emperors)