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点一定更优,所以我们真的不会走回头路
我们是否可以跑最短路。
---
*/
标签:CF605E,read,void,int,MAXN,template,inline,Intergalaxy,Trips
From: https://www.cnblogs.com/Dark-Romance/p/16789289.html