[概率,期望]CF605E Intergalaxy Trips

\(\texttt{link}\)

\(E(i)\) 为从 \(i\)\(n\) 的期望天数,则答案为 \(E(1)\)

类似 \(Dijkstra\),每次可以确定 \(E\) 最小的点不会再被松弛,设这些点为 \(a_1,a_2,...,a_m\)

若有 \(u \longrightarrow a_i\),则满足 \(\forall j < i, u \longrightarrow a_j\) 的路径当天并未出现,则有转移:

\[E(u) = 1 + \sum\limits_{i=1}^m E(a_i) * p(u,a_i) * \prod\limits_{j=1}^{i-1}(1-p(u,a_j)) \]

若所有可行路径都没出现,则 \(E(u) = \prod\limits_{i=1}^m (1-p(u,a_i))E(u)\)

总转移:\(E(u) = \dfrac{1 + \sum\limits_{i=1}^m E(a_i) * p(u,a_i) * \prod\limits_{j=1}^{i-1}(1-p(u,a_j))}{1 - \prod\limits_{i=1}^m (1-p(u,a_i))}\)

时间复杂度 \(O(n^2)\)

\(\texttt{Code:}\)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n, vis[N];
double p[N][N], sp[N], E[N];
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	for (int j = 1; j <= n; j++)
		scanf("%lf", &p[i][j]), p[i][j] /= 100.0;
	for (int i = 1; i < n; i++) E[i] = 1, sp[i] = 1 - p[i][n];
	for (int i = 1; i < n; i++) {
		double mn = 0; int id = 0;
		for (int j = 1; j < n; j++)
		if (!vis[j]) {
			if (!id) mn = E[j] / (1 - sp[j]), id = j;
			else if (mn > E[j] / (1 - sp[j])) mn = E[j] / (1 - sp[j]), id = j;
		}
		vis[id] = 1;
		E[id] = E[id] / (1 - sp[id]);
		for (int j = 1; j < n; j++)
		if (!vis[j]) {
			E[j] += E[id] * p[j][id] * sp[j];
			sp[j] *= 1 - p[j][id];
		}
	}
	printf("%.6lf", E[1]);
	return 0;
}
posted @ 2021-11-04 07:25  klii  阅读(28)  评论(0)    收藏  举报