• 概率/期望DP初步——BZOJ1415 聪聪和可可


    期望相关:

      数学期望,可以简单理解的加权平均数。设有一系列的值$x_i$,每个值被取到的概率为$p_i$,则期望$E=sumlimits_{i=1}^n p_i x_i$。

      期望具有线性性:$$E(aX+bY)=aE(X)+bE(Y)$$ $$E(XY)=E(X)E(Y)$$ 大概就是说求期望的时候正着反着乱序着乱搞求出来的都是对的。。。

    基于期望的线性性,我们可以在概率和期望之间建立一定的递推关系,这样就可以通过动态规划来解决一些概率问题。

    比如NOI2005的聪聪和可可。

    题目大意:给定一个无向图,聪聪在起点,可可在终点,每个时刻聪聪会沿最短路走向可可两步(如果有多条最短路走编号最小的点),然后可可会等概率向周围走或不动,求平均多少个时刻后聪聪和可可相遇。

    设聪聪在节点$x$,可可在节点$y$

    设$f[u][v]$为聪聪在$u$可可在$v$时聪聪抓住可可的期望时间,$p[u][v]$为为聪聪在$u$可可在$v$时聪聪下一步会到达的节点,$degree[v]$为节点$v$的度;

    显然,当$x=y$时$f[x][y]=0$;当$0<dis[x][y] leqslant 2$时$f[x][y]=1$。

     当$dis[x][y]>2$时,$$f[x][y]=frac{f[p[x][y]][y]+sumlimits_{e(y,k)} f[p[x][y]][k]}{degree[x]+1}$$

    对每个节点进行一次SPFA求出p[][]

    然后根据上述状态转移方程记忆化搜索就好。

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstdio>
     5 #include<queue>
     6 #define foru(i,x,y) for(int i=x;i<=y;i++)
     7 using namespace std;
     8 const int N=1e4+10;
     9 struct edge{int to,nxt;}e[N*2];
    10 queue<int> q;
    11 int head[N],vis[N],d[N],ne,n,m,s,t,p[1005][1005];
    12 double f[1005][1005];
    13 void add(int a,int b){e[++ne]=(edge){b,head[a]};head[a]=ne;}
    14 void spfa(int x){
    15     memset(d,127,sizeof(d));
    16     memset(vis,0,sizeof(vis));
    17     q.push(x);d[x]=0;vis[x]=1;
    18     while(!q.empty()){
    19         int k=q.front();q.pop();
    20         vis[k]=0;
    21         for(int i=head[k];i;i=e[i].nxt){
    22             int v=e[i].to;
    23             if(d[v]>d[k]+1||(d[v]==d[k]+1&&k<p[v][x])){
    24                 d[v]=d[k]+1;
    25                 p[v][x]=k;
    26                 if(!vis[v]){
    27                     q.push(v);
    28                     vis[v]=1;
    29                 }
    30             }
    31         }
    32     }
    33 }
    34 
    35 double dfs(int x,int y){
    36     if(f[x][y]!=-1)return f[x][y];
    37     if(x==y){f[x][y]=0;return 0;}
    38     if(p[x][y]==y||p[p[x][y]][y]==y){f[x][y]=1;return 1;};
    39     f[x][y]=dfs(p[p[x][y]][y],y);int d=0;
    40     for(int i=head[y];i;i=e[i].nxt){
    41         d++;
    42         int v=e[i].to;
    43         f[x][y]+=dfs(p[p[x][y]][y],v);
    44     }
    45     (f[x][y]/=d+1);
    46     f[x][y]+=1;
    47     return f[x][y];
    48 }
    49 
    50 int main(){
    51     int u,v;
    52     scanf("%d%d",&n,&m);
    53     scanf("%d%d",&s,&t);
    54     foru(i,1,m){
    55         scanf("%d%d",&u,&v);
    56         add(u,v);add(v,u);
    57     }
    58     foru(i,1,n)foru(j,1,n)f[i][j]=-1;
    59     foru(i,1,n)spfa(i);
    60     double ans=dfs(s,t);
    61     printf("%.3lf
    ",ans);
    62     return 0;
    63 }

    DP一直是弱项,总是找不到套路,还是多做点题吧。

  • 相关阅读:
    零基础学python-2.24 一些常用函数
    零基础学python-2.23 模块
    零基础学python-2.22 回到我们的游戏 加入文件和异常
    tcp协议:三次握手四次挥手详解---总结
    centos7安装jmeter + ant
    centos7安装jenkins
    centos7安装tomcat
    centos7安装jdk (jdk-8u161-linux-x64.tar.gz 和 java-1.8.0-openjdk* 介绍)
    波浪场景jp@gc
    阶梯场景jp@gc
  • 原文地址:https://www.cnblogs.com/y-m-y/p/6773867.html
Copyright © 2020-2023  润新知