HDU 5001 Walk 概率DP

题目大意:

一个人随即从一个点出发,到达邻接点的概率相同,求出走d步都不会到达1~n点的每一项的不可能概率(这里第一次随即取的点是要求的点也算到达过了)

 

这道题开始一直在计算到达那一点的可能性,最后用1-ans[i],但到最后还是没有找到自己哪里错了,有机会再看看

 

后来直接计算不可能概率,通过dp找到一直走d步后还能到达非自己所要的num的那些点,每次访问到num点,都直接跳过不理它,使其概率不能下传就行了

然后在solve函数中,把所有除num外的dp[j][d]相加就成功了

 

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <queue>

 5 #include <vector>

 6 using namespace std;

 7 #define N 52

 8 vector<int> G[N];

 9 int n,m,d;

10 double dp[N][10005],ans[N];

11 void bfs(int num)

12 {

13     memset(dp,0,sizeof(dp));

14     for(int i=1;i<=n;i++)

15         if(i!=num)

16             dp[i][0] = 1.0/n;

17         else dp[i][0]=0; //对于已经到达的点不往下继续传值

18 

19     for(int i=0;i<d;i++){

20         for(int j=1;j<=n;j++){

21             for(int m=0;m<(int)G[j].size();m++){

22                 //因为求不到的可能,所以遇到自己需要到达的点就不计算,使其保持空值,无法向下传值

23                 if(G[j][m]!=num){

24                     dp[G[j][m]][i+1]+=dp[j][i]*1.0/(int)G[j].size();

25                     //cout<<dp[j][i]<<endl;

26                 }

27             }

28         }

29     }

30 }

31 

32 void solve()

33 {

34     memset(ans,0,sizeof(ans));

35     for(int i=1;i<=n;i++){

36         bfs(i);

37         for(int j=1;j<=n;j++){

38             if(j!=i)

39                 ans[i]+=dp[j][d];

40                 //将所有能走到最后一步且不是自己所要终点的可能性相加即是不到i的概率

41         }

42     }

43 }

44 

45 int main()

46 {

47     int T,a,b;

48     scanf("%d",&T);

49     while(T--){

50 

51         scanf("%d%d%d",&n,&m,&d);

52 

53         for(int i=1;i<=n;i++) G[i].clear();

54 

55         for(int i=0;i<m;i++){

56             scanf("%d%d",&a,&b);

57             G[a].push_back(b);

58             G[b].push_back(a);

59         }

60 

61         solve();

62 

63         for(int i=1;i<=n;i++)

64             printf("%.10f\n",ans[i]);

65     }

66     return 0;

67 }

 

你可能感兴趣的:(HDU)