• 小A的旅行(绿豆蛙的归宿)【期望DP】


     

    Description

    给出一个有向无环的连通图,起点为1,终点为N,每条边都有一个长度。小A从起点出发,走向终点。
    到达每一个顶点时,如果有K条离开该点的道路,小A可以选择任意一条道路离开该点,并且走向每条路的概率为 1/K 。
    现在小A想知道,从起点走到终点的所经过的路径总长度期望是多少?

    Input

    第一行: 两个整数 N M,代表图中有N个点、M条边
    第二行到第 1+M 行: 每行3个整数 a b c,代表从a到b有一条长度为c的有向边

    Output

    从起点到终点路径总长度的期望值,四舍五入保留两位小数。

    Sample Input

    4 4

    1 2 1

    1 3 2

    2 3 3

    3 4 4

    Sample Output

    7.00

    Hint

    对于30%的数据  N<=50

    对于70%的数据  N<=1000

    对于100%的数据  N<=100000,M<=2*N,边权<=1000

     

    -----------------------------------

    测试数据:https://files.cnblogs.com/files/Syameimaru/tour.zip

    -------------------------------------------------------------------------------------------------------

    题解:

    对于这道题,我们很容易想到,用动态规划的思想解决有关期望的问题。

    可以观察到,每个店的期望值,都只与他的子节点有关,具体关系为:

    f[i]=(f[j]+w)/d[i]

    其中,f[i[表示从i节点,到达终点的路径的期望。

    注意,这里我们不用f[i]表示到达i点概率的期望值,因为如果这样表示,会导致状态转移代价过大,使算法不够优秀,并且有更多的细节(只考虑能够到大的父节点计算入度),不够优秀,所以我们才用倒序来推。

    时间复杂度 O(n),我们可以按照拓扑序倒序来转移。

    当然,我们没必要真的进行拓扑排序,记忆化dp就好

    下面是胡搞的代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #include<queue>
     5 #define rep(i,a,b) for(register int i = (a);i<=(b);++i)
     6 const int maxn = 120000 ;
     7 struct Edge {
     8     int v,dist;
     9     Edge(int v,int dist):v(v),dist(dist){}
    10 };
    11 std::vector<Edge> edges;
    12 std::vector<int> G1[maxn],G2[maxn];
    13 std::queue<int> Q,Q2;
    14 double f[maxn];
    15 int n,m,a,b,v,inq[maxn],tp[maxn];
    16 double dfs(int x) {
    17     if(f[x]) return f[x];
    18     if(x==n) return 0;
    19     for(register int i=0;i<G1[x].size();i++) {
    20         Edge e = edges[G1[x][i]];
    21         f[x]+=dfs(e.v)+e.dist;
    22     }
    23     f[x]/=G1[x].size();
    24     return f[x];
    25 }
    26 int main() {
    27     freopen("tour.in","r",stdin);
    28     freopen("tour.out","w",stdout);
    29     scanf("%d%d",&n,&m);
    30     rep(i,1,m){
    31         scanf("%d%d%d",&a,&b,&v);
    32         inq[b]++;edges.push_back(Edge(b,v));
    33         edges.push_back(Edge(a,v));
    34         int num = edges.size();
    35         G1[a].push_back(num-2);
    36         G2[b].push_back(num-1);
    37     }
    38     dfs(1);
    39     printf("%.2lf",f[1]);
    40     return 0;
    41 }
    View Code
  • 相关阅读:
    Json.Net学习笔记(八) 序列化的回调方法
    PowerDesigner 使用的一些技巧(转)
    Json.Net学习笔记(十三) 缩小序列化Json的大小
    Json.Net学习笔记(十四) JSON的部分序列化
    MSDTC服务配置 今天碰到的情况
    Json.Net学习笔记(十一) CustomCreationConverter
    让工作自动化
    Json.Net学习笔记(十二) 协议解析
    Json.Net学习笔记(九) 异常处理
    通过PB认证
  • 原文地址:https://www.cnblogs.com/Syameimaru/p/9294173.html
Copyright © 2020-2023  润新知