CF605E Intergalaxy Trips

分析

首先可以贪心得到,我们肯定优先走向期望天数小的节点。如果那个边未出现,才走其他的边。

同时,可以用像 Prim 的方法进行维护,每一次选出未用来更新的最小点,然后标记并更新其他未标记点。

同时,我们有:
\[ f_x=1+f_1p_{x,a_1}+f_2p_{x,a_2}(1-p_{x,a_1})+...+f_xp_{x,x}\prod(1-p_{x,a_i}) \]

化简:
\[ f_x=\frac{1+\sum\limits_{i}f_{i}p_{x,i}\prod\limits_{j=1}^{i-1}(1-p_{x,a_j})}{1-\prod\limits_{i}(1-p_{x,a_i})} \]

然后可以发现直接维护 f 的值不方便,那么我们可以维护分子分母上的和式和积式。

code:

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N=1e3+7;
int n;
double p[N][N];
double a[N],b[N];
bool vis[N];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        a[i]=b[i]=1;
        for(int j=1;j<=n;j++){
            scanf("%lf",&p[i][j]);
            p[i][j]*=0.01;
        }
    }
    a[n]=b[n]=0;
    for(int i=1;i<=n;i++){
        double res=1e20;
        int o=0;
        for(int j=1;j<=n;j++)
            if(!vis[j]){
                double f=a[j]/(1-b[j]);
                if(res>f) res=f,o=j;
            }
        if(o==1){
            printf("%.10lf\n",res);
            return 0;
        }
        vis[o]=1;
        for(int j=1;j<=n;j++)
            if(!vis[j]){
                a[j]+=b[j]*p[j][o]*res;
                b[j]*=1-p[j][o];
            }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Hikigaya/p/11975982.html