Live2D

CF605E Intergalaxy Trips

link

Solution

不是很难,不知道为啥之前没做出来。

不难看出我们有如下转移式:

\[f_{u}=\sum f_{v}\times P_{u,v}\times (\prod_{f_t<f_v} (1-P_{u,t}))+1 \]

那么我们可以发现的是,这个玩意一定不会产生环,因为有环的话不如停在自己比较优秀。然后直接跑最短路即可,就是每次找一个用当前已知 \(f\) 算出来的最小 \(f\) 加进去。

可以做到 \(\Theta(n^2)\),但是我比较懒,所以写了一个 \(\Theta(n^3)\),但也能过。

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN 1005

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int n,tot,seq[MAXN];bool vis[MAXN];
double f[MAXN],pre[MAXN],g[MAXN],pro[MAXN][MAXN];

signed main(){
	read (n);
	for (Int u = 1;u <= n;++ u) for (Int v = 1;v <= n;++ v) scanf ("%lf",&pro[u][v]),pro[u][v] /= 100;
	memset (f,0x3f,sizeof (f)),f[n] = 0,vis[n] = 1,seq[tot = 1] = n;
	while (tot < n && !vis[1]){
		int pos = 0;
		for (Int u = 1;u <= n;++ u) if (!vis[u]){
			double tmp = 0,lst = 1;
			for (Int i = 1;i <= tot;++ i){
				int v = seq[i];
				if (vis[v]) tmp += f[v] * pro[u][v] * lst;
				lst *= 1 - pro[u][v];
			}
			g[u] = (tmp + 1) / (1 - lst);
			if (!pos || g[u] < g[pos]) pos = u;
		}
		seq[++ tot] = pos,vis[pos] = 1,f[pos] = g[pos];
	}
	printf ("%.6f\n",f[1]);
    return 0;
}
/*
f[n]=0
f[u]=\sum_{S} p(S)*min(f[S])+1
f[u]=\sum_{v} f[v]*p[u][v]*(\prod_{t} [f[t]<f[v]] (1-p[u][t]))+1
---
我们考虑从u->v意味着f[u]一定大于f[v],否则我留在u点一定更优,所以我们真的不会走回头路
我们是否可以跑最短路。
---
*/
posted @ 2022-10-13 18:43  Dark_Romance  阅读(29)  评论(0编辑  收藏  举报