zoukankan      html  css  js  c++  java
  • 绿豆蛙的归宿【期望】【DFS】

    题目大意:

    若一个点有k条出边,则走每条出边的概率均为1k。给出一个有向无环图,求从起点走到终点的所经过的路径总长度期望。
    Input

    4 4
    1 2 1
    1 3 2
    2 3 3
    3 4 4

    Output

    7.00

    思路:

    这很明显是一道数学期望的题目。但是由于之前没有做过这类的题目,所以做起来还是很吃力。
    拿样例来说
    这里写图片描述


    1一开始肯定是有1.00的几率到达的,它有两条出边,分别到达点2和点3,那么,点2和点3就各有0.50的几率到达。
    这里写图片描述
    那么,点2又有一条出边到达点3,那么点3到达的几率就在原来的基础上又加上了点2的到达几率,所以点3的到达几率为1.00。
    这里写图片描述
    然后点3就只有一条出边,通向点4,所以点4到达几率就为1.00
    这里写图片描述

    每次当我们访问到一个点时,就讲答案sum加上它到达的概率×边权,即

    sum+=s[x]num[x]×e[i].dis

    且这个点的期望也要加上s[x]num[x]
    然后继续向下搜索,搜到点n时就返回,然后将期望值减去s[x]num[x],防止重复计算。


    代码:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    int n,m,x,y,t;
    double z,sum,s[300011],num[300011],head[300011],k;
    
    struct edge  //邻接表
    {
        int to,next;
        double dis;
    }e[500011];
    
    void add(int from,int to,double d)  //建边
    {
        t++;
        e[t].dis=d;
        e[t].to=to;
        e[t].next=head[from];
        head[from]=t;
    }
    
    void dfs(int x)
    {
        if (x==n) return;  //到达终点
        for (int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            double l=s[x]/num[x];  //计算路径长度期望
            s[v]+=l;  //加上期望
            sum+=e[i].dis*l;  //答案
            dfs(v);
            s[v]-=l;  //减掉期望
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%lf",&x,&y,&z);
            add(x,y,z);  //建边
            num[x]++;
        }
        s[1]=1.00;  
        dfs(1);
        printf("%0.2lf\n",sum);
        return 0;
    }
  • 相关阅读:
    第八章 多线程编程
    Linked List Cycle II
    Swap Nodes in Pairs
    Container With Most Water
    Best Time to Buy and Sell Stock III
    Best Time to Buy and Sell Stock II
    Linked List Cycle
    4Sum
    3Sum
    Integer to Roman
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998839.html
Copyright © 2011-2022 走看看