• Atcoder Beginner Contest 144 F- Fork the Road(概率DP/期望DP)


    Problem Statement

     

    There is a cave consisting of NN rooms and MM one-directional passages. The rooms are numbered 11 through NN .

    Takahashi is now in Room 11 , and Room NN has the exit. The ii -th passage connects Room sisi and Room titi (sisi < titi ) and can only be traversed in the direction from Room sisi to Room titi . It is known that, for each room except Room NN , there is at least one passage going from that room.

    Takahashi will escape from the cave. Each time he reaches a room (assume that he has reached Room 11 at the beginning), he will choose a passage uniformly at random from the ones going from that room and take that passage.

    Aoki, a friend of Takahashi's, can block one of the passages (or do nothing) before Takahashi leaves Room 11 . However, it is not allowed to block a passage so that Takahashi is potentially unable to reach Room NN .

    Let EE be the expected number of passages Takahashi takes before he reaches Room NN . Find the value of EE when Aoki makes a choice that minimizes EE .

    Constraints

     

    • 2N6002≤N≤600
    • N1MN(N1)2N−1≤M≤N(N−1)2
    • si<tisi<ti
    • If i!=ji!=j , (si,ti)(sj,tj)(si,ti)≠(sj,tj) . (Added 21:23 JST)
    • For every v=1,2,...,N1v=1,2,...,N−1 , there exists ii such that v=siv=si .

    Input

     

    Input is given from Standard Input in the following format:

    NN
    
     MM
    
    
    s1s1
    
     t1t1
    
    
    ::
    
    
    sMsM
    
     tMtM
    
    
    

    Output

     

    Print the value of EE when Aoki makes a choice that minimizes EE . Your output will be judged as correct when the absolute or relative error from the judge's output is at most 10610−6 .

    Sample Input 1

     

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

    Sample Output 1

     

    1.5000000000
    

    If Aoki blocks the passage from Room 11 to Room 22 , Takahashi will go along the path 134 with probability 1212 and 14 with probability 1212 . E=1.5E=1.5 here, and this is the minimum possible value of EE .

    Sample Input 2

     

    3 2
    1 2
    2 3
    

    Sample Output 2

     

    2.0000000000
    

    Blocking any one passage makes Takahashi unable to reach Room NN , so Aoki cannot block a passage.

    Sample Input 3

     

    10 33
    3 7
    5 10
    8 9
    1 10
    4 6
    2 5
    1 7
    6 10
    1 4
    1 3
    8 10
    1 5
    2 6
    6 9
    5 6
    5 8
    3 6
    4 8
    2 7
    2 9
    6 7
    1 2
    5 9
    6 8
    9 10
    3 9
    7 8
    4 5
    2 10
    5 7
    3 5
    4 7
    4 9
    

    Sample Output 3

     

    3.0133333333
    https://blog.csdn.net/wjl_zyl_1314/article/details/102811697?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task题意在这
    总算搞明白怎么写了...重点有两个,一个是转移方程。概率DP的一大特点是如果最终状态明确,一般选择从最终状态逆推,所以这里dp[i]表示从i到终点的期望道路数,转移方程为dp[i]=1+(Σdp[k])/len,其中k为i这个点的出边的终点(满足逆推,即由终状态到初始状态),len为i这个点的出边数(结合概率考虑一下,len条道路每条被选择的概率为1/len),这个+1也很好理解,因为i到k必定会走一条路。这是不考虑删边的情况。
    那么删边该怎么办呢?只需要对于枚举每个点考虑删除它的出边终点里期望最大的那个就可以了(因为逆推,i这个点之后的状态都确定了)。代码写法参考了上面的博客QwQ。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <algorithm>
    #define N 605
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,m;
    vector<int>v[N];
    double dp[N]={0};
    double process(int p)//对于p这个顶点删除其连着的最大的出边 
    {
        int i,j;
        for(i=1;i<=n;i++)dp[i]=0.0;
        dp[n]=0.0;//特别强调一下 
        for(i=n-1;i>=1;i--)
        {
            if(v[i].size()==1&&p==i)//i出度为1且 要删它的边 
            {
                dp[i]=INF;//删了以后必不能到达 所以设置为INF 
                continue;
            }
            double len=v[i].size()-(p==i);//如果i是枚举到的p的话要减1 因为删边了 
            dp[i]=1.0;//先加上1 
            double mmax=0;//。找到最大的,如果p==i的话要在最后减掉 
            for(j=0;j<v[i].size();j++)
            {
                double temp=dp[v[i][j]];//获取每个出边终点的dp值 
                mmax=max(mmax,temp);
                dp[i]+=temp*1.0/len;//结合转移方程理解 
            }
            if(i==p)dp[i]-=mmax*1.0/len;
        }
        //cout<<dp[1]<<endl;
        return dp[1]; 
    }
    int main()
    {
        cin>>n>>m;
        int i;
        for(i=1;i<=m;i++)
        {
            int s,t;
            scanf("%d%d",&s,&t);
             v[s].push_back(t);//出边 
        }
        double ans=INF;
        for(i=n;i>=1;i--)
        {
            ans=min(ans,process(i));
        }
        printf("%.10lf",ans);//注意输出格式 
        return 0;
    }
  • 相关阅读:
    Understanding Unix/Linux Programming-ls指令练习二
    Understanding Unix/Linux Programming-ls指令练习一
    Understanding Unix/Linux Programming-who指令练习
    复习自控有感——20160307
    根轨迹法的校正正目标、原理和方法
    Understanding Unix/Linux Programming-cp指令练习
    树莓派交叉编译环境在Linux下的建立
    Vue最全指令大集合————VUE
    JS实现动态瀑布流及放大切换图片效果(js案例)
    JS实现自动轮播图效果(js案例)
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/12547069.html
Copyright © 2020-2023  润新知