Foreign Postcards Gym - 101190F 概率DP

题目链接:https://vjudge.net/problem/Gym-101190F
转自:https://blog.csdn.net/dormousenone/article/details/73699630
题意:1.对于一叠 n 张卡片,随机取前 k 张
2.若取到的 k 张的第一张为 W ,则 k 张卡片的状态全部翻转。
3.将 k 张卡片在桌面上展示
4.若一叠卡片仍有剩余,则继续上述操作
问最后桌面上为 W 的卡片的期望?
思路:首先计算对于第 i 张卡片,其为 k 张中的第一张的概率,依次为 1, 1/n , 1/(n−1) … (第一张概率必定是1,选取第一张的概率为1/n,这样第二张就成了第一张,概率等于1/n*1)
令 dp[i][0] 表示第 i 张卡片不翻的概率,dp[i][1] 表示第 i 张卡片翻转的概率,则 dp[i][0]+dp[i][1] = 1 。
令第 i 张为首张的概率为 p
若第 i 张为 W ,则其不翻的概率为 dp[i][0] = (1-p) * dp[i-1][0],因为这张W牌不翻面的概率等于它不是第一张并且上一张也不翻面的概率,下同。
若第 i 张为 C ,则其不翻的概率为 dp[i][0] = p + (1-p) * dp[i-1][0]
第 i 张翻转的概率为 dp[i][1] = 1 - dp[i][0]
统计每张最终为 W 的概率和即为问题期望

#include 
using namespace std;
const int N = 1e6 + 10;
double dp[N][2];
int main()
{
    freopen("foreign.in", "r", stdin);
    freopen("foreign.out", "w", stdout);
    string s;
    double p,ans=0;
    cin>>s;
    int l=s.length();
    if(s[0]=='W')
    {
        dp[0][0]=0;//不翻
        dp[0][1]=1;//翻
    }
    else
    {
        dp[0][0]=1;
        dp[0][1]=0;
    }
    for(int i=1; i<l; i++)
    {
        double p=(double)1/(l-i+1);
        if(s[i]=='W')
        {
            dp[i][0]=(1-p)*dp[i-1][0];
            dp[i][1]=p+(1-p)*dp[i-1][1];
        }
        else
        {
            dp[i][0]=p+(1-p)*dp[i-1][0];
            dp[i][1]=(1-p)*dp[i-1][1];
        }
        if(s[i]=='W')
        {
            ans+=dp[i][0];
        }
        else
        {
            ans+=dp[i][1];
        }
    }
    printf("%.10f",ans);
}

你可能感兴趣的:(DP)