[洛谷P1850]换教室:期望DP+最短路

分析:

Floyd求任意两点间最短路后正向期望DP。

代码:

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

inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x;
}

const int MAXN=2005;
int n,m,V,E,c[MAXN],d[MAXN],dis[305][305];
double kk[MAXN],f[MAXN][MAXN][2];

int main(){
    memset(dis,0x3f,sizeof dis);
    n=read(),m=read(),V=read(),E=read();
    for(int i=1;i<=V;i++) dis[i][i]=0;
    for(int i=1;i<=n;i++) c[i]=read();
    for(int i=1;i<=n;i++) d[i]=read();
    for(int i=1;i<=n;i++) scanf("%lf",&kk[i]);
    for(int i=1;i<=E;i++){
        int u=read(),v=read(),w=read();
        dis[u][v]=dis[v][u]=std::min(dis[u][v],w);
    }
    for(int k=1;k<=V;k++)
        for(int i=1;i<=V;i++)
            for(int j=1;j<=V;j++)
                dis[i][j]=std::min(dis[i][j],dis[i][k]+dis[k][j]);
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
            f[i][j][0]=f[i][j][1]=1e9;
    f[1][0][0]=0;
    f[1][1][1]=0;
    for(int i=2;i<=n;i++)
        for(int j=0;j<=m;j++){
            f[i][j][0]=std::min(f[i][j][0],std::min(f[i-1][j][0]+dis[c[i-1]][c[i]],
                f[i-1][j][1]+dis[c[i-1]][c[i]]*(1-kk[i-1])+dis[d[i-1]][c[i]]*kk[i-1]));
            if(j) f[i][j][1]=std::min(f[i][j][1],std::min(
                f[i-1][j-1][0]+dis[c[i-1]][c[i]]*(1-kk[i])+dis[c[i-1]][d[i]]*kk[i],
                f[i-1][j-1][1]+dis[d[i-1]][d[i]]*kk[i-1]*kk[i]+dis[d[i-1]][c[i]]*kk[i-1]*(1-kk[i])
                +dis[c[i-1]][d[i]]*(1-kk[i-1])*kk[i]+dis[c[i-1]][c[i]]*(1-kk[i-1])*(1-kk[i])));
        }
    double ans=1e9;
    for(int i=0;i<=m;i++) ans=std::min(ans,std::min(f[n][i][0],f[n][i][1]));
    printf("%.2lf\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9757565.html