您的位置:首页 > 其它

hdu5001 Walk

2015-08-04 10:21 288 查看
第一次做概率dp的题目 ,其处理的方式和普通dp是差不多的,只是将表示的值变成了概率 ,还有就是概率要怎么算是个难题 。

该题求从某个点 i 出发,走d步,不经过i的概率,我们可以求经过 i 的概率,用d[i][j]表示已经走了i步,当前在j点的概率(因为步数是一个天然的序,我们可以用来定义阶段)。

那么显然,如果没有经过j点,概率为0 ,所以初始化为0 ; 每次经过一个点j,那么经过j点的概率就要发生一次变化,假设从k点经过的j点,那么d[i][j]的概率就要加上1/(于k点相连的结点数) ;

所以说,其实和普通的dp一样,还是注意那几个点:阶段、顺序、依赖、d[i[[j]表示的是什么意思、状态如何转移 etc

细节参见代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 55;
int T,n,u,v,m,d;
double dp[10005][55];
vector<int> g[maxn];
void init() {
        scanf("%d%d%d",&n,&m,&d);
        for(int i=0;i<=n;i++) g[i].clear();
        for(int i=0;i<m;i++) {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
}
double solve(int u) {
    memset(dp,0,sizeof(dp));
    dp[0][0] = 1;//初始化边界
    double ans = 0;
    for(int i=0;i<=d;i++) {
        for(int j=0;j<=n;j++) {
            if(j == u) continue;
            double p = 1.0/g[j].size();
            for(int k=0;k<g[j].size();k++) {
                int v = g[j][k];
                dp[i+1][v] += (dp[i][j] * p); //在第i+1步经过v点的概率。
            }
        }
        ans += dp[i+1][u]; //各步经过u点的概率
    }
    return 1.0 - ans;
}
int main() {
    scanf("%d",&T);
    while(T--) {
        init();
        for(int i=1;i<=n;i++) g[0].push_back(i);//初始化边界
        for(int i=1;i<=n;i++) {
            printf("%.10lf\n",solve(i));
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: