Codeoforces 605E Intergalaxy Trips 期望dp

题意

有n个点,第i个点到第j个点的路径在每个时刻有 p i , j 的概率出现,每个时刻可以留在原地或走某条出现了的边。问在最优决策下从1走到n的期望时间是多少。
n 1000

分析

f i 表示从 i 开始走到 n 的期望时间是多少。
考虑当我们位于某个点 x 上时会如何决策,对于当前所有能到达的点,必然会选择到达一个 f y 最小的 y
假设把所有点按 f 值从小到大排序后得到的序列为 a 1 , a 2 , . . . , a n ,显然有 a 1 = n
不难得到转移

f a i = 1 + j = 1 i f a j p a i , a j k = 1 j 1 ( 1 p a i , a k )

那么我们就可以每次动态求出 a i ,然后进行转移即可。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

const int N=1005;

int n,p[N][N];
double f[N],g[N];
bool vis[N];

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            scanf("%d",&p[i][j]);
    for (int i=1;i<n;i++) f[i]=g[i]=1;
    for (int i=1;i<=n;i++)
    {
        double mn=1e9;int pos=0;
        for (int j=1;j<=n;j++)
            if (!vis[j]&&g[j]<1&&f[j]/(1-g[j])<mn) mn=f[j]/(1-g[j]),pos=j;
        if (!pos) break;
        vis[pos]=1;
        f[pos]/=(1-g[pos]);
        for (int j=1;j<=n;j++)
            if (!vis[j])
            {
                f[j]+=g[j]*f[pos]*((double)p[j][pos]/100);
                g[j]*=(double)(100-p[j][pos])/100;
            }
    }
    printf("%.10lf",f[1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_33229466/article/details/80869769