AT_dp_j Sushi

前置知识

什么是数学期望?

类似于加权平均,离散型随机变量的一切可能的取值 $x_i$ 与对应的概率 $p(x_i)$ 乘积之和称为该离散型随机变量的数学期望 $E(x)$。

因此,$E(x)$ 可表示为:$$E(x)=\sum^n_{i=1}x_ip(x_i)$$

分析

本题最大的特点是每个盘子中至多有 $3$ 个寿司

如果有两个盘子都有 $x$ 个寿司,那么它们就没有区别。

也就是说,无论这两个盘子排在哪里,最终输出的答案是一致的。无端联想排列组合。

因此,我们只需要关心不同寿司个数的盘子的数量,这些盘子的顺序对最终答案没有任何影响

实现

$dp_{i,j,k}$ 表示当当前寿司数为 $1$ 的盘子有 $i$ 个,寿司数为 $2$ 的盘子有 $j$ 个,寿司数为 $3$ 的步数为 $k$ 个时,吃完全部所需的期望。

dp 方程如下:$$dp_{i,j,k}=\frac{n}{i+j+k}+dp_{i-1,j,k}\times\frac{i}{i+j+k}+dp_{i+1,j-1,k}\times\frac{j}{i+j+k}+dp_{i,j+1,k-1}\times\frac{k}{i+j+k}$$

显然,维度 $k$ 具有单调性,因此 $k$ 需要放在循环外层。

Code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=310;

int n,a[5];
double dp[MAXN][MAXN][MAXN];

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int tmp;
        cin>>tmp;
        a[tmp]++;
    }
    for(int k=0;k<=n;k++)
    {
        for(int j=0;j<=n;j++)
        {
            for(int i=0;i<=n;i++)
            {
                double s=i+j+k;
                if(s!=0)//防止 i,j,k 同时为零
                {
                    if(i)dp[i][j][k]+=dp[i-1][j][k]*i/s;
                    if(j)dp[i][j][k]+=dp[i+1][j-1][k]*j/s;
                    if(k)dp[i][j][k]+=dp[i][j+1][k-1]*k/s;
                    dp[i][j][k]+=(double)n/s;
                }
            }
        }
    }
    printf("%.10lf\n",dp[a[1]][a[2]][a[3]]);
    return 0;
}
posted @ 2023-06-09 22:40  H2ptimize  阅读(11)  评论(0)    收藏  举报  来源