caioj1270: 概率期望值1:小象涂色

DP深似海,得其得天下。——题记

叕叕叕叕叕叕叕叕叕叕叕(第∞次学DP内容)被D飞了,真的被DP(pa)了。这次D我的是大叫着第二题比较难(小象涂色傻b题)的Mocha(zzz)大佬,表示搞个概率DP,后面还有什么区间、状压、插头DP,不知道这个坑怎么填。唉,心疼。

讲讲这道题吧,在ZZZ大佬的帮助下终于看懂了题,然后他告诉我:

其实全部的箱子都是一样的

然后聪明(???)的我就发现,答案要求的其实就是每个箱子,颜色最后变成0~c-1的期望,再乘以颜色那个数字罢了

So,弄一个f数组,f[i][j]表示染了i次色,变成j颜色的期望。

然后,上代码。很好理解,我写了注释。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int cs[110];
double f[110][110];//f[i][j]表示染了i次色,变成j颜色的期望 
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,c,K,mmax=0,x,y;
        scanf("%d%d%d",&n,&c,&K);
        memset(cs,0,sizeof(cs));
        for(int i=1;i<=K;i++)
        {
            scanf("%d%d",&x,&y);
            for(int j=x;j<=y;j++)
            {
                cs[j]++;
                mmax=max(mmax,cs[j]);
            }
        }
        
        memset(f,0,sizeof(f));f[0][1]=1.0;//一开始全部都是1 
        for(int i=1;i<=mmax;i++) 
            for(int j=0;j<c;j++) 
            {
                f[i][j]+=f[i-1][j]/2;//有1/2的概率,不会被涂色
                for(int k=0;k<c;k++)f[i][(j*k)%c]+=f[i-1][j]/(2*c);//枚举所有可能被涂的颜色
                //被涂的概率是1/2,被涂k颜色概率为1/c,合起来就是1/(2*c) 
            }
            
        double ans=0.0;
        for(int i=1;i<=n;i++)//枚举每一个箱子 
            for(int j=0;j<c;j++)//被涂成j颜色 
                ans+=f[cs[i]][j]*j;//i被涂有cs[i]次,由于要求颜色和,乘以颜色 
        printf("%.9lf
",ans);
    }
    return 0;
}

 

原文地址:https://www.cnblogs.com/AKCqhzdy/p/7606303.html