题目大意
聪聪总会走最短路线接近可可,可可以等概率走到相邻节点或留在原节点,聪聪可可轮流走,聪聪先走,一次最多走2步,可可一次最多1步,问聪聪吃到可可(同节点)的期望步数。
题解
由于聪聪总会向可可靠近,而且移动是固定的,因此考虑预处理出所有情况下聪聪的移动方向e[i,j]=聪聪在i点,可可在j点时,聪聪会移动到的点。
这个跑SPFA解决,貌似从可可出发还是聪聪出发都没有太大关系。
由于聪聪和可可的位置即可描述当前状态,因此设dp[i,j]
显然当
ei,j=j或eei,j,j=j
时,聪聪可以一轮内吃掉可可,此时
dp[i,j]=1
。
否则可可有
1|adjj|+1
的可能性原地不动、或走一步。
显然聪聪一次走2步更优,故此时
fi,j=avgk∈adjj∪{j}(f[eei,j,j][k])+1
#include <cstdio>
#include <cstring>
const int N = 1001, M = 10005;
int h[N], p[M], v[M], vis[N], q[M * 5], dis[N][N], e[N][N], cnt = 0;
double f[N][N];
void add(int a, int b) {
p[++cnt] = h[a]; h[a] = cnt; v[cnt] = b;
p[++cnt] = h[b]; h[b] = cnt; v[cnt] = a;
}
void spfa(int s) {
int f = 0, r = 0, u, i;
q[r++] = s; dis[s][s] = 0; e[s][s] = s;
while (f < r) {
u = q[f++]; vis[u] = 0;
for (i = h[u]; i; i = p[i]) {
if (dis[s][v[i]] > dis[s][u] + 1) {
dis[s][v[i]] = dis[s][u] + 1;
if (!vis[v[i]])
q[r++] = v[i], vis[v[i]] = 1;
}
if (dis[s][v[i]] == dis[s][u] + 1 && u < e[v[i]][s])
e[v[i]][s] = u;
}
}
}
double dp(int x, int y) {
double &r = f[x][y], c = 0, d = 1;
if (r) return r;
if (x == y) return 0;
if (e[x][y] == y || e[e[x][y]][y] == y) return r = 1;
c = dp(e[e[x][y]][y], y);
for (int i = h[y]; i; i = p[i])
c += dp(e[e[x][y]][y], v[i]), ++d;
return r = c / d + 1;
}
int main() {
int n, m, a, b, x, y, i;
scanf("%d%d%d%d", &n, &m, &a, &b);
memset(dis, 127, sizeof dis);
memset(e, 127, sizeof e);
while (m--) {
scanf("%d%d", &x, &y); add(x, y);
}
for (i = 1; i <= n; ++i) spfa(i);
printf("%.3lf", dp(a, b));
return 0;
}