首页 > 代码库 > poj 5001 Walk &&2014 ACM/ICPC Asia Regional Anshan Online 1005(dp)
poj 5001 Walk &&2014 ACM/ICPC Asia Regional Anshan Online 1005(dp)
http://acm.hdu.edu.cn/showproblem.php?pid=5001
思路:dp计算出途径每个点的总概率,1-x即为所求解。
dp题,先介绍下dp[i][j]为第j步走在第i个点的概率,那么dp[i][j]=dp[x1][j-1]+dp[x2][j-1]+...,x1,x2为i 的相邻节点。上一步在相邻节点这一步才能走到该点嘛。
每个点概率要一个一个的算,当算到第ii个点时(没打错,ii个点与代码对应),从起点推起,起点嘛,算是第0步吧,每个点被选中几率1.0/n,直接计入ans,并将该状态记零,因为此部分概率已计入总概率,不用产生后继状态,防止重复计数。然后以每一步为一层,更新每个节点的概率,碰到所求的点ii 时将概率计入总数并该状态记零,同上,避免状态重复计算。如此即可。
代码(g++ %f不过,c++ %f %lf 都过,知道的同学路过请求告知):
#include<iostream> #include<map> #include<cstdio> #include<string> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=55; const int maxm=3000; int first[maxn],v[maxm],nex[maxm],out[maxn]; double dp[55][10005]; int ecnt; void add_(int a,int b) { out[a]++; v[ecnt]=b; nex[ecnt]=first[a]; first[a]=ecnt++; } int main() { int T,n,m,k,a,b; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&k); ecnt=0; memset(out,0,sizeof out); memset(first,-1,sizeof first); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); add_(a,b);add_(b,a); } for(int j=1;j<=n;j++)dp[j][0]=1.0/n; for(int ii=1;ii<=n;ii++) { double ans=1.0/n; dp[ii][0]=0; for(int i=1;i<=k;i++) { for(int j=1;j<=n;j++) { dp[j][i]=0; for(int e=first[j];~e;e=nex[e]) dp[j][i]+=(dp[v[e]][i-1]/out[v[e]]); if(j==ii)ans+=dp[j][i],dp[j][i]=0; } } dp[ii][0]=1.0/n; printf("%.10f\n",1-ans); } } return 0; }
poj 5001 Walk &&2014 ACM/ICPC Asia Regional Anshan Online 1005(dp)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。