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;
}
posted @ 2019-12-03 11:57  天才美少女雪乃  阅读(138)  评论(0编辑  收藏  举报