首页 > 其他分享 >数学——概率期望

数学——概率期望

时间:2022-09-24 21:33:15浏览次数:68  
标签:概率 期望 int double sum 数学 return dp

P4316 绿豆蛙的归宿

拓扑排序+概率期望

概率期望题一般有两种做题方式:正推,逆推
对于终止状态确定的一般用逆推
对于起始状态确定的一般用正推

  1. 逆推
    这道题中,定义dp数组 \(f_i\) 表示从 \(i\) 到终点的路径长度期望,显然,\(f_n=0\),可以采取逆推的策略,式子如下:

\[f_x=\sum_{以x为起点的边}\frac{f_{y}+cost}{outdeg_x} \]

  1. 正推
    如果定义dp数组 \(f_i\) 表示从1到 \(i\) 的路径长度期望,则 \(f_1=0\),可以进行正推
    然而我不会,逃

P4206 聪聪与可可

奇妙的预处理

因为点数极小,所以可以直接bfs预处理最短路,来预处理聪聪每次往哪里走,然后记忆化搜索每次可可随机走的情况即可

Code

#include<bits/stdc++.h>
#define N 1005
using namespace std;

int n,E,c,m;
int dis[N][N],vis[N][N],step[N][N],v[N][N];
struct edge{
    int v,nxt;
}e[N*2];
int head[N],tot,deg[N];
double dp[N][N];
inline void add(int u,int v);
void bfs(int x);
double dfs(int i,int j);

int main(){
    cin>>n>>E;
    cin>>c>>m;
    for(int i=1;i<=E;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
        deg[u]++,deg[v]++;
    }
    memset(dis,0x7f,sizeof(dis));
    for(int i=1;i<=n;i++) bfs(i);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            int mem=0;
            for(int k=head[i];k;k=e[k].nxt){
                if(dis[j][e[k].v]<dis[j][mem])
                    mem=e[k].v;
                if(dis[j][e[k].v]==dis[j][mem])
                    mem=min(mem,e[k].v);
            }
            step[i][j]=mem;
        }
    printf("%.3lf",dfs(c,m));
}

inline void add(int u,int v){
    e[++tot].v=v;
    e[tot].nxt=head[u];
    head[u]=tot;
}

void bfs(int x){
    queue<int> q;
    q.push(x);
    dis[x][x]=0;
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[x][u]=true;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(!vis[x][v]){
                vis[x][v]=true;
                dis[x][v]=dis[x][u]+1;
                q.push(v);
            }
        }
    }
}

double dfs(int i,int j){
    if(v[i][j]) return dp[i][j];
    v[i][j]=true;
    if(i==j) return dp[i][j]=0;
    int fir=step[i][j],sec=step[fir][j];
    if(fir==j||sec==j) return dp[i][j]=1;
    double sum=0;
    for(int k=head[j];k;k=e[k].nxt)
        sum+=dfs(sec,e[k].v);
    sum+=dfs(sec,j);
    return dp[i][j]=sum/(double)(deg[j]+1)+(double)1;
}

P1654 OSU!

这道题要维护 \(\sum E(x^3)\),但明显 \(E(x^3)\ne E(x)^3\)
逐步考虑 \(E(x),E(x^2)\)
考虑状态转移方程

\[E(x+1)=(E(x)+1)*p_i \\ E((x+1)^2)=E(x^2+2x+1)=(E(x^2)+2E(x)+1)*p_i \\ E((x+1)^3)=E(x^3+3x^2+3x+1)=E(x^3)+(3E(x^2)+3E(x)+1)*p_i \\ \]

维护三个变量转移即可

Code
#include<bits/stdc++.h>
#define N 100005
using namespace std;

int n;
double p,x1,x2,x3;

int main(){
    cin>>n;
    for(int i=1;i<=n;++i){
        scanf("%lf",&p);
        x3=x3+(3*x2+3*x1+1)*p;
        x2=(x2+2*x1+1)*p;
        x1=(x1+1)*p;
    }
    printf("%.1lf",x3);
}

Red is good

题面:
桌面上有R张红牌和B张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1美元,黑牌则付出1美元。可以随时停止翻牌,在最优策略下平均能得到多少钱。

设dp数组 \(f_{i,j}\) 表示有 \(i\) 个红牌 \(j\) 个黑牌时候的最优期望
\(f_{i,j}\) 可以由 \(f_{i-1,j},f_{i,j-1}\) 推出:

\[f_{i,j}=(f_{i-1,j}+1)*\frac{i}{i+j}+(f_{i,j-1}-1)\frac{j}{i+j} \]

意义为最后一张翻的牌为红牌或黑牌对答案的影响

这道题的关键在于“最优策略”是什么,推状态转移方程的途中可以看出来,如果 \(f_{i,j}<0\) 的话,其实在采取最优策略的情况下已经不能够保证正收益了,所以不拿为上,直接令 \(f_{i,j}=0\)

Code
#include<bits/stdc++.h>
#define N 5005
using namespace std;

int r,b;
double dp[N][N];

int main(){
    cin>>r>>b;
    for(int i=0;i<=r;i++)
        for(int j=0;j<=b;j++){
            if(i>0) dp[i][j]+=(double)i/(double)(i+j)*(dp[i-1][j]+1);
            if(j>0) dp[i][j]+=(double)j/(double)(i+j)*(dp[i][j-1]-1);
            if(dp[i][j]<0) dp[i][j]=0;
        }
    printf("%.6lf",dp[r][b]-0.0000005);
}

标签:概率,期望,int,double,sum,数学,return,dp
From: https://www.cnblogs.com/Rolling-star/p/16726708.html

相关文章