expect dp
It was my first time doing this kind of question, and I searched a lot of relevant information before I could understand it.
law
1. Expectation can be decomposed into a weighted sum of multiple sub-expectations, and the weight is the probability of the sub-expectation occurring, that is,
E ( a A + b B + … ) E ( a A + b B + … ) E(aA+bB+…)
= a E ( A ) + b E ( B ) + … + 1 E ( a A + b B + … ) =a E ( A ) + b E ( B ) + … + 1 E(aA+bB+…) =aE(A)+bE(B)+…+1E(aA+bB+…)
= a E ( A ) + b E ( B ) + … + 1 E ( a A + b B + … ) = aE(A) + bE(B) +…+1E(aA+bB+…) =aE(A)+bE(B)+…+1E(aA+bB+…)
= a E ( A ) + b E ( B ) + … + 1 ; =aE(A)+bE( B)+…+1; =aE(A)+bE(B)+…+1;
2. Term and time, general d p [ n ] = 0 , d p [ 0 ] dp[n]=0,dp[0] dp[n]=0,dp[0] is the answer;
3. Solving process, find various situations multiplied by the probability of this situation happening, and sum up;
4. Probability DP must be initialized!
5. Different from conventional solutions, mathematical expectations are often deduced in reverse.
Several common methods for setting up transfer equation arrays
设 f [ i ] f[ i ] f[i] Indicative reason < /span> i i i The expectation that the state will become the final state
Set it directly according to the meaning of the question
Add the selected things Array, such as f [ i ] [ j ] f[i][j] f[i][ j] 五用第 i i i Product selection j j j f [ i ] [ j ] f[i][j] f[i][ j] Displayed i i i 个 A A A Goods,
j j j 个 B B B Material expectations
code:
#include <bits/stdc++.h>
using namespace std;
#define maxn 305
double f[maxn][maxn][maxn];//状态:f[i,j,k]:有i个一个寿司盘子,j个两个寿司盘子,k个三个寿司盘子的期望值。
int a[5];
int n;
int main() {
scanf( "%d", &n );
for ( int i = 1, x; i <= n; i ++ ) scanf( "%d", &x ), a[x] ++; //统计各种寿司盘有多少
for ( int k = 0; k <= n; k ++ )
for ( int j = 0; j <= n; j ++ )
for ( int i = 0; i <= n; i ++ )
if ( i or j or k ) {
//数学期望 P=Σ每一种状态*对应的概率,没啥可说的。
if ( i ) f[i][j][k] += f[i - 1][j][k] * i / (i + j + k); //个数为1的盘子吃掉一个就没有了;
if ( j ) f[i][j][k] += f[i + 1][j - 1][k] * j / (i + j + k); //个数为2的盘子吃掉一个就少了一个个数为2的盘子,多一个个数为1的盘子;
if ( k ) f[i][j][k] += f[i][j + 1][k - 1] * k / (i + j + k); //个数为3的盘子吃掉一个就少了一个个数为3的盘子,多一个个数为2的盘子
f[i][j][k] += n * 1.0 / (i + j + k);
}
printf( "%.10f\n", f[a[1]][a[2]][a[3]] );
}
Okay, this can be considered a template question, right?