您的位置:首页 > 其它

hdu5001 walk 【概率dp】

2016-07-25 15:41 295 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5001

题意:给你一个n个点m条边的无向图,问你任意从一的点出发走d步后,不经过某个点的概率,输出那个点的概率。

分析:枚举一个点,表示不从该点出发经过该点的概率,因为从该点出发的路径,一直都是经过该点的,比如说到a点的概率是p1,它如果连两个点那么ans=p1+p1*0.5+p1*0.5

这里我们就重复算了a的概率。

用dp[j][i]表示用j步到了i的概率。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 51
#define Mm 10005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
struct edge {
int v,next;
}e[Mn*Mn/2];
int head[Mn],tot;
void addedge(int u,int v) {
e[tot].v=v;
e[tot].next=head[u];
head[u]=tot++;
}
int n,m,d;
int num[Mn];
double dp[Mm][Mn];
int main() {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%d%d",&n,&m,&d);
CLR(num,0);
CLR(head,-1);
tot=0;
for(int i=1;i<=m;i++) {
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
num[u]++;
num[v]++;
}
for(int i=1;i<=n;i++) addedge(0,i);
num[0]=n;
for(int i=1;i<=n;i++) {
CLR(dp,0);
dp[0][0]=1.0;
double ans=0.0;
for(int j=0;j<=d;j++) {
for(int u=0;u<=n;u++) {
if(u==i) continue;
if(j!=0&&u==0) continue;
if(j==0&&u!=0) continue;
double a=1.0/num[u];
for(int p=head[u];~p;p=e[p].next) {
int v=e[p].v;
dp[j+1][v]+=dp[j][u]*a;
}
}
ans+=dp[j+1][i];
}
printf("%.10f\n",1.0-ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: