HDU 5001 Walk

来源:互联网 发布:c语言中取整怎么表示 编辑:程序博客网 时间:2024/04/28 14:08

题意:

连通无向图  随机选起点  随机乱走  可以重复走点  问  每个点有多大几率不被路过

思路:

一看就是DP题…

但是开始的时候陷入了僵局  我是想先算路过每个点的概率然后用1减去这个概率  但是由于可以重复路过  所以无法判断是不是第一次经过这个点

所以我们应该直接做不路过的概率  即类似bfs的一步步走  如果走到了要计算的点就停下来  意思就是除了要计算概率的那个点不能走以外  其他都能走  最后统计下概率的和就是不路过这个点的概率

PS:

这题一定要用邻接表  我一开始看这图可能是完全图而且n只有50  就用了邻接矩阵  然后就T了  换邻接表就1218MS

代码:

#include<cstdio>#include<iostream>#include<string>#include<cstring>#include<algorithm>#include<cmath>#include<map>#include<set>#include<vector>#include<cassert>using namespace std;typedef long long LL;#define Q 401#define N 51#define M 10001#define inf 2147483647#define mod 1000000007#define lowbit(x) (x&(-x))int t, n, m, p, tot;int head[N], d[N];double dp[M][N];struct edge {int v, next;} ed[N * N * 2];void add(int u, int v) {ed[tot].v = v;ed[tot].next = head[u];head[u] = tot++;}int main() {int i, j, k, f;double ans;scanf("%d", &t);while (t--) {scanf("%d%d%d", &n, &m, &p);for (i = 1; i <= n; i++) {head[i] = -1;d[i] = 0;}tot = 0;for (i = 1; i <= m; i++) {scanf("%d%d", &j, &k);d[j]++;d[k]++;add(j, k);add(k, j);}for (i = 1; i <= n; i++) {for (j = 1; j <= n; j++) {if (i != j)dp[0][j] = 1.0 / n;elsedp[0][j] = 0;}for (f = 1; f <= p; f++) {for (j = 1; j <= n; j++)dp[f][j] = 0;for (j = 1; j <= n; j++) {if (i == j)continue;for (k = head[j]; ~k; k = ed[k].next)dp[f][ed[k].v] += dp[f - 1][j] / d[j];}}ans = 0;for (j = 1; j <= n; j++) {if (i != j)ans += dp[p][j];}printf("%f\n", ans);}}return 0;}


0 0
原创粉丝点击