题解 CF605E 【Intergalaxy Trips】

关怀他人

2021-01-27 23:14:34

Solution

### CF605E #### Solution 设$E(u)$表示从$u$到$n$的期望步数,考虑下一步,如果是走到$v$且$E(v)\geq E(u)$,那么当前这一步的最优策略肯定是停在原地。 所以我们永远不会走到一个比当前期望步数大的点,所以我们可以考虑将所有答案按从小到大的顺序算出,并以此扩展。 设$u$的后继分别为$v_i$且$E$非降,那么 $$ E(u)=\sum_i \dfrac{E(v_i)}{1-\prod_{j=1}^n(1-p_{v_i,j})}p_{u,v_i}\prod_{j=1}^{i-1} (1-p_{u,v_j})+1 $$ 后面的$\prod_{j=1}^{i-1} (1-p_{u,v_j})$表示$v_i$可以走且所有期望步数小于$v_i$的都不能走,而前面除以$1-\prod_{j=1}^n(1-p_{v_i,j})$的原因是要去掉$v_i$没法走到其他地方的概率,因为$E_i$计算的是不考虑自环的概率,最后再加上当前这一步的贡献$1$即可。 用类似 $\mathrm{dijkstra}$ 的方式每次取最小的转移即可。 时间复杂度 $\mathcal O(n^2)$ #### Code ```cpp int n; int vis[MAXN],a[MAXN]; double p[MAXN][MAXN],E[MAXN],prod[MAXN]; 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; if(n == 1) {printf("0\n"); return 0;} for(int i = 1;i <= n;i++) E[i] = 1, prod[i] = 1 - p[i][n]; vis[n] = 1; a[1] = n; for(int i = 1;i <= n;i++){ double minval = llINF; int pos = 0; for(int j = 1;j <= n;j++){ if(!vis[j] && E[j] / (1 - prod[j]) < minval){ pos = j; minval = E[j] / (1 - prod[j]); } } vis[pos] = 1; for(int j = 1;j <= n;j++) E[j] += E[pos] / (1 - prod[pos]) * p[j][pos] * prod[j], prod[j] *= (1 - p[j][pos]); } printf("%.8f\n",E[1] / (1 - prod[1])); return 0; } ```