解法
(好像在哪裏見過幾乎一樣的問題?)
考慮這種圖上的期望一般倒着算,所以可以從終點反推回起點。
然後考慮我們更新點到終點的距離的過程,我們每次選出一個目前到終點距離最近的點,用它去更新和它相鄰的點的距離,這個是也是最短路的思想。由於沒有負權邊,所以考慮用迪傑斯特拉
轉移方程
#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;
}