首页 > 代码库 > HDU 5001 Walk

HDU 5001 Walk

题意:

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

思路:

一看就是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;
				else
					dp[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;
}


HDU 5001 Walk