hdu5001 概率dp

来源:互联网 发布:软件开发工程师是什么 编辑:程序博客网 时间:2024/06/09 19:58

传送门

题意:给定一个无向图,从每个点的出发概率都相等,从每个点到它的连接点的概率也相同,给定固定的步数,求不经过某个点的概率

思路:设第i步经过第j点的概率为dp[i][j],那么dp[i][j]=∑dp[i-1][k]*1/temp[k],其中k为与j连接的点,temp[k]为与k点连接的点的个数,那么1减去j点各个步经过的点的概率就是不经过j点的概率了。其实开始就有点想不通,如果一直在任意两个点之间来回走,第一组数据还怎么做到不经过的概率是0的?代码中有个判断条件:if(j==x) continue;就保证了在求dp[i][j]时不能由dp[i-1][j]参与,似乎也保证了A->B->A这种情况是不可以的

完整代码:

#include<cstring>#include<cmath>#include<cstdio>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int N=1e4+5;double dp[N][55];double temp[55];int con[55][55];double ans[55];int n,m,d;double solve(int x){    memset(dp,0,sizeof(dp));    for(int i=1;i<=n;i++)        dp[1][i]=1/(double)n;    double ans=1/(double)n;    for(int i=1;i<=d;i++)    {        for(int j=1;j<=n;j++)        {            if(j==x) continue;            double p=1.0/temp[j];            for(int k=1;k<=n;k++)            {                if(con[j][k])                {                    dp[i+1][k]+=(dp[i][j]*p);                }            }        }        ans+=dp[i+1][x];    }    return 1.0-ans;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        memset(temp,0,sizeof(temp));        memset(con,0,sizeof(con));        scanf("%d%d%d",&n,&m,&d);        while(m--)        {            int a,b;            scanf("%d%d",&a,&b);            con[a][b]=1;///表示a、b连接            con[b][a]=1;///表示b、a连接            temp[a]=temp[a]+1.0;///求连接a点的个数            temp[b]=temp[b]+1.0;///求连接b点的个数        }        for(int i=1;i<=n;i++)        {            printf("%.10lf\n",solve(i));        }    }    return 0;}


原创粉丝点击