zoukankan      html  css  js  c++  java
  • E. Intergalaxy Trips

    完全图,(1 leq n leq 1000)每一天边有 (p_{i,j}=frac{A_{i,j}}{100}) 的概率出现,可以站在原地不动,求 (1) 号点到 (n) 号点期望天数。


    注意 Windows 下 double 读入异常地慢,而自己 Linux 下读入巨快……

    首先,每个点肯定都会往期望更小的点走。如果目标点期望比自己大,还不如原地不动。

    所以点构成了一个全序关系。显然对于每个点,它的决策是确定的。

    所以当确定一个点的最小期望值时,需要确定一个排列 (P) 使得方程解出来的 (E_1) 最小,且 (E_{P_i}) 随着 (i) 增加单调不降:

    [E_{P_i} = sum_{j leq i} E_{P_j} cdot p_{P_i,P_j} cdot prod_{k<j} left( 1 - p_{P_i,P_k} ight) ]

    但是这样考虑太麻烦了,我们考虑倒着做:因为当 (i) 越小时, (E_{P_i}) 的式子越简单。

    因此考虑从 (n) 号点往回递推,当我们确定 (P_i) 时,对于每个点,它的式子前几项都已经求出来了,对 (j = i) 移项,每次取能解出的最小的 (E)。即 dijkstra 地求。

    需要类似前缀和优化的技巧。

    考虑正确性:

    不妨假设最终的 (E_i) 互不相同。

    我们假设确定 (P_i) 时最小的那个叫 (A),然而我们顶替了一个 (E) 更大的 (B) 上去,那么 (A) 可以不走到 (P_j (j geq i)) 的点达到更优解,那么就发生了 (E_A < E_B),全序关系被破坏,矛盾。

    #include <bits/stdc++.h>
    
    const int MAXN = 1010;
    double P[MAXN][MAXN];
    double E[MAXN], prod[MAXN], dis[MAXN];
    bool vis[MAXN];
    int n;
    int main() {
    	std::ios_base::sync_with_stdio(false), std::cin.tie(0);
    	std::cin >> n;
    	for (int i = 1; i <= n; ++i)
    		for (int j = 1, t; j <= n; ++j)
    			std::cin >> t, P[i][j] = t / 100.;
    	for (int i = 1; i < n; ++i)
    		dis[i] = 1e100, E[i] = prod[i] = 1;
    	dis[n] = 0;
    	for (int i = 1; i <= n; ++i) {
    		int at = 0;
    		for (int j = 1; j <= n; ++j)
    			if (!vis[j] && (!at || dis[at] > dis[j])) at = j;
    		vis[at] = true;
    		for (int j = 1; j <= n; ++j) if (!vis[j]) {
    			E[j] += dis[at] * prod[j] * P[j][at];
    			prod[j] *= 1 - P[j][at];
    			dis[j] = E[j] / (1 - prod[j]);
    		}
    	}
    	std::cout << std::fixed << std::setprecision(15) << dis[1] << std::endl;
    	return 0;
    }
    
    
  • 相关阅读:
    线程循环的故事
    代码质量
    代码质量控制之异常控制
    面对象静态结构描述方法
    解决maven下载依赖包,pom文件错误问题
    Spring学习笔记
    java编程命名规范
    powershell使用
    vert.x中future的简单使用
    idea调整import包的顺序
  • 原文地址:https://www.cnblogs.com/daklqw/p/12009106.html
Copyright © 2011-2022 走看看