题目

https://www.luogu.org/problemnew/show/P1850

思路

期望DP

很容易想到设f[i][j]为前i个时间段,换了j次,的期望长度。结果发现转移不了,因为我们不知道它的出发点在哪。

自然,数组就变成了f[i][j][0..1]表示是否申请成功

DP时每句所有情况,记住乘上概率

预处理一个floyd即可

代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=3e3+77,T=307,inf=0x3f3f3f3f;
int a[N],b[N],n,m,t,p;
double e[N],d[T][T],ans=(double)inf,f[N][N][2];
int main()
{
    scanf("%d%d%d%d",&n,&m,&t,&p);
    for(int i=1; i<=n; i++) scanf("%d",&a[i]);
    for(int i=1; i<=n; i++) scanf("%d",&b[i]);
    for(int i=1; i<=n; i++) scanf("%lf",&e[i]);
    for(int i=1; i<=t; i++) for(int j=1; j<=t; j++) d[i][j]=(double)inf;
    for(int i=1; i<=p; i++)
    {
        int x,y; double z;
        scanf("%d%d%lf",&x,&y,&z);
        d[x][y]=min(d[x][y],z); d[y][x]=min(d[y][x],z);
    }
    for(int i=1; i<=t; i++) d[i][i]=0;
    for(int k=1; k<=t; k++) for(int i=1; i<=t; i++) for(int j=1; j<=t; j++)
        d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    for(int i=0; i<=n; i++) for(int j=0; j<=m; j++)
    {
        f[i][j][0]=inf; f[i][j][1]=inf;
    }
    f[1][0][0]=0; f[1][1][1]=0;
/*  for(int i=1; i<=n; i++) for(int j=1; j<=m; j++)
    {
        int x=a[i-1],y=b[i-1],x1=a[i],y1=b[i];
        f[i][j][0]=min(f[i-1][j][0]+d[x][x1],
        f[i-1][j][1]+d[x][x1]*(1-e[i-1])+d[y][x1]*e[i-1]);

        f[i][j][1]=min(f[i-1][j-1][0]+d[x][x1]*(1-e[i])*e[i]+d[x][y1]*e[i],
        f[i-1][j-1][1]+d[y][x1]*(1-e[i])*e[i-1]+d[y][y1]*e[i]*e[i-1]);
    }*/
    for(int i=2; i<=n; i++)
    {
        int mn=min(i,m);
        double w1=d[a[i-1]][a[i]],
        w2=d[b[i-1]][a[i]]*e[i-1]+d[a[i-1]][a[i]]*(1-e[i-1]),
        w3=d[a[i-1]][b[i]]*e[i]+d[a[i-1]][a[i]]*(1-e[i]),
        w4=d[a[i-1]][a[i]]*(1-e[i-1])*(1-e[i])+d[a[i-1]][b[i]]*(1-e[i-1])*e[i]+d[b[i-1]][a[i]]*(1-e[i])*e[i-1]+d[b[i-1]][b[i]]*e[i-1]*e[i];
        for(int j=0;j<=mn;j++)
        {
            f[i][j][0]=min(f[i-1][j][0]+w1,f[i-1][j][1]+w2);
            if(j)f[i][j][1]=min(f[i-1][j-1][0]+w3,f[i-1][j-1][1]+w4);
        }  
    }
    for(int i=0; i<=m; i++) ans=min(ans,min(f[n][i][0],f[n][i][1]));
    printf("%.2lf",ans);
}