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
- 2≤N≤6002≤N≤600
- N−1≤M≤N(N−1)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,...,N−1v=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 10−610−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 1
→ 3
→ 4
with probability 1212 and 1
→ 4
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; }