【DP】【AsiaRegionalAnshanOnline2014】HDU5001Walk

来源:互联网 发布:股票数据分析模型 编辑:程序博客网 时间:2024/05/21 19:40

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5001

英文题目必备翻译:给一个无向图,某君一开始随机选择一个点,然后走d步,每步随机跳转到一个相邻结点,即使是走过的也可以,问d步走完后每个点没走过的概率是多少。

做这个题目我们必须事先明白一个事情,d步那就是没有走过的点的概率等于d步走到其他点的概率和;所以我们就可以枚举来计算走到其他点的概率和来计算没有走到点的概率;

运用DP状态转移解决问题。首先,枚举d步不走的点。然后枚举i-1步可能到达的点,更新各条边(枚举各条邻边)的走的概率,有点类似于广搜,一步一步来走。直接看代码吧。(这个题目很多人的博客都写错了,害的我还理解错了。。。orz...)

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int N=10005;double dp[N][55];void init(int n){    memset(dp,0,sizeof(dp));    for(int i=1;i<=n;i++) dp[0][i]=1.0/n;}int main(){    int t,m,n,d,u,v;    scanf("%d",&t);    while(t--){        scanf("%d%d%d",&n,&m,&d);        vector<int> g[55];        for(int i=0;i<m;i++){            scanf("%d%d",&u,&v);            g[u].push_back(v);            g[v].push_back(u);        }        for(int l=1;l<=n;l++){          //  枚举没有走到的点;            init(n);        //  对dp数组进行初始化;            for(int i=1;i<=d;i++){      //  枚举步数;                for(int j=1;j<=n;j++){   //  枚举i-1步可能到达的点;                    if(j==l) continue;      //  不走这一点;                    int cnt=g[j].size();                    double p=1.0/cnt;                    for(int k=0;k<cnt;k++){     //  枚举各边对应的邻边;                        if(g[j][k]==l) continue;    //  这点出发的也不行;                        dp[i][g[j][k]]+=p*dp[i-1][j];   //  dp[i][j]表示走了i步到j的概率;                    }                }            }            double ans=0;            for(int i=1;i<=n;i++){                ans+=dp[d][i];      //  dp[i][j]表示走了i步到j的概率;所有的加起来,没有走到l的概率;            }            printf("%.10lf\n",ans); //  ans就是d步不走到l的概率;        }    }    return 0;}


 

0 0
原创粉丝点击