codeforces 605E

本文解析了一道在洛谷上发布的图论题目,通过逆向思维从终点反推起点来求解最小期望路径。利用迪杰斯特拉算法,考虑到没有负权边,通过更新点到终点的距离来实现最短路径的计算,最终给出了解题代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

luogu链接

解法

(好像在哪里见过几乎一样的问题?)
考虑这种图上的期望一般倒着算,所以可以从终点反推回起点。
然后考虑我们更新点到终点的距离的过程,我们每次选出一个目前到终点距离最近的点,用它去更新和它相邻的点的距离,这个是也是最短路的思想。由于没有负权边,所以考虑用迪杰斯特拉

转移方程
d [ u ] = ∑ v d [ v ] ∗ p [ u ] [ v ] ∗ ( 1 − p r [ u ] ) , 更 新 的 时 候 按 d 从 小 到 大 的 顺 序 d[u]=\sum_v d[v]*p[u][v]*(1-pr[u]),更新的时候按d从小到大的顺序 d[u]=vd[v]p[u][v](1pr[u]),d
d [ i ] : i 到 n 的 最 小 期 望 d[i]:i到n的最小期望 d[i]in
p r [ i ] : i 已 经 转 移 走 的 概 率 ( d j 更 新 的 时 候 需 要 ) pr[i]:i已经转移走的概率(dj更新的时候需要) pr[i]idj)
s u m [ i ] : 已 经 计 算 过 的 到 i 的 期 望 sum[i]:已经计算过的到i的期望 sum[i]i

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char c=getchar();int t=0,f=1;
	while((!isdigit(c))&&(c!=EOF)){if(c=='-')f=-1;c=getchar();}
	while((isdigit(c))&&(c!=EOF)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
	return t*f;
}
int n,vis[1005],a[1005];
double p[1005][1005],d[1005],pr[1005],sum[1005];
signed main(){
	n=read();
	for(int i=1;i<=n;i++){
		int x=0;
		sum[i]=pr[i]=1.0;
		for(int j=1;j<=n;j++){
			x=read();
			p[i][j]=x*0.01;
		}
	}
	vis[n]=1;
	a[1]=n;d[0]=1e18;
	for(int i=2;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(vis[j])continue;
			sum[j]+=d[a[i-1]]*p[j][a[i-1]]*pr[j];
			pr[j]*=(1-p[j][a[i-1]]),d[j]=sum[j]/(1-pr[j]);
		}
		int pos=0;
		for(int j=1;j<=n;j++){
			if((!vis[j])&&(d[j]<d[pos]))pos=j;
		}
		vis[pos]=1;a[i]=pos;
	}
	printf("%.10lf\n",d[1]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值