zoukankan      html  css  js  c++  java
  • [CF605E] Intergalaxy Trips

    问题描述

    • n 个点的有向完全图。
    • (i o j) 的边每天出现的概率均为 (p_{i,j}),若 (i = j),有 (p_{i,j}) = 1。
    • 每天选择一条存在的出边走过去。
    • 求最优策略下从 1 到 (n) 的期望天数。
    • (n le 10^3)

    样例输入

    3
    100 50 50
    0 100 80
    0 0 100

    样例输出

    2
    100 30
    40 100

    解析

    一个比较好想的策略是每次走到终点的期望天数最少的点。但这样很难确定转移,因此我们不妨倒过来转移,从n号点出发。对于期望天数第(i)小的节点,设其编号为(a_i),我们不难得到以下转移方程:

    [f_{a_i}=1 imes prod_{j=1}^{i-1}(1-p_{a_i,a_j})+sum_{j=1}^{i}f_{a_j} imes p_{a_i,a_j}prod_{k=1}^{j-1}(1-p_{a_i,a_k}) ]

    (q_i=sum_{j=1}^{i-1}(1-p_{a_i,a_j})),稍作转化,将(f_{a_i})提到等式的同一边即可。然后用类似Dijkstra的思路,每次取当前最小的节点更新即可。更新时可以同时计算(q_i)

    代码

    #include <iostream>
    #include <cstdio>
    #define N 1002
    using namespace std;
    int n,i,j;
    double f[N],p[N][N],p1[N];
    bool vis[N];
    int read()
    {
    	char c=getchar();
    	int w=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c<='9'&&c>='0'){
    		w=w*10+c-'0';
    		c=getchar();
    	}
    	return w;
    }
    int main()
    {
    	n=read();
    	for(i=1;i<=n;i++){
    		for(j=1;j<=n;j++){
    			int x=read();
    			p[i][j]=0.01*x;
    		}
    	}
    	for(i=1;i<=n;i++) p1[i]=1;
    	p1[n]=0;
    	for(i=1;i<=n;i++){
    		double minx=1e20;
    		int id;
    		for(j=1;j<=n;j++){
    			if(!vis[j]&&(f[j]+p1[j])/(1-p1[j])<minx) minx=(f[j]+p1[j])/(1-p1[j]),id=j;
    		}
    		vis[id]=1;f[id]=minx;
    		if(id==1){
    			printf("%.10lf
    ",minx);
    			break;
    		}
    		for(j=1;j<=n;j++){
    			if(!vis[j]) f[j]+=p[j][id]*p1[j]*(f[id]+1),p1[j]*=(1-p[j][id]);
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    android系统移植与驱动开发概述
    产品常用网址
    Java泛型、反射、集合、多线程
    Java常用类
    Java异常处理
    Java面向对象(二)
    Java面向对象(一)
    Java基础知识
    友链
    退役了
  • 原文地址:https://www.cnblogs.com/LSlzf/p/13443685.html
Copyright © 2011-2022 走看看