• [最短路][期望DP]luogu P1850 换教室


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

    分析

    先全部跑一边dij,把距离求出来

    我们设f[i][j][0/1]表示第i个时段,用了j次换教室机会,当前教室有无使用机会的最小期望

    $f[i+1][j][0]=min(f[i][j][0]+dis[c[i]][c[i+1]],f[i][j][1]+dis[c[i]][c[i+1]]*(1-p[i])+dis[d[i]][c[i+1]]*p[i])$

    $f[i+1][j+1][1]=min(f[i][j][0]+dis[c[i]][c[i+1]*(1-p[i+1])+dis[c[i]][d[i+1]]*p[i+1],f[i][j][1]+dis[c[i]][c[i+1]]*(1-p[i])*(1-p[i])+dis[c[i]][d[i+1]]*(1-p[i])*p[i+1]+dis[d[i]][c[i+1]]*p[i]*(1-p[i+1])+dis[d[i]][d[i+1]]*p[i]*p[i+1]$

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <memory.h>
    using namespace std;
    const int N=2e3+10;
    struct Heap {
        int i,dis;
        friend bool operator < (Heap a,Heap b) {
            return a.dis>b.dis;
        }
    };
    struct Graph {
        int v,w,nx;
    }g[2*90010];
    int cnt,list[N];
    int dis[N][N],c[N],d[N];
    double f[N][N][2],p[N];
    int n,m,v,e;
    
    void Add(int u,int v,int w) {
        g[++cnt]=(Graph){v,w,list[u]};list[u]=cnt;
        g[++cnt]=(Graph){u,w,list[v]};list[v]=cnt;
    }
    
    void Dij(int v0) {
        priority_queue<Heap> q;
        while (!q.empty()) q.pop();
        q.push((Heap){v0,0});dis[v0][v0]=0;
        while (!q.empty()) {
            Heap a=q.top();q.pop();
            int u=a.i,d=a.dis;
            if (dis[v0][u]<d) continue;
            for (int i=list[u];i;i=g[i].nx)
                if (dis[v0][g[i].v]>dis[v0][u]+g[i].w)
                    dis[v0][g[i].v]=dis[v0][u]+g[i].w,q.push((Heap){g[i].v,dis[v0][g[i].v]});
        }
    }
    
    int main() {
        scanf("%d%d%d%d",&n,&m,&v,&e);
        for (int i=1;i<=n;i++) scanf("%d",&c[i]);
        for (int i=1;i<=n;i++) scanf("%d",&d[i]);
        for (int i=1;i<=n;i++) scanf("%lf",&p[i]);
        for (int i=1,u,v,w;i<=e;i++) scanf("%d%d%d",&u,&v,&w),Add(u,v,w);
        memset(dis,0x3f,sizeof dis);
        for (int i=0;i<=v;i++) dis[0][i]=0;
        for (int i=1;i<=v;i++) Dij(i);
        for (int i=0;i<=n;i++)
            for (int j=0;j<=m;j++)
                for (int k=0;k<2;k++) f[i][j][k]=2147483647;
        f[0][0][0]=f[0][0][1]=0;
        for (int i=0;i<n;i++)
            for (int j=0;j<=min(i,m);j++) {
                f[i+1][j][0]=min(f[i+1][j][0],f[i][j][0]+dis[c[i]][c[i+1]]);
                f[i+1][j][0]=min(f[i+1][j][0],f[i][j][1]+dis[c[i]][c[i+1]]*(1.0-p[i])+dis[d[i]][c[i+1]]*p[i]);
                if (j<=min(i,m-1)) f[i+1][j+1][1]=min(f[i+1][j+1][1],f[i][j][0]+dis[c[i]][c[i+1]]*(1.0-p[i+1])+
                dis[c[i]][d[i+1]]*p[i+1]);
                if (j<=min(i,m-1)) f[i+1][j+1][1]=min(f[i+1][j+1][1],f[i][j][1]+dis[c[i]][c[i+1]]*(1.0-p[i])*(1.0-p[i+1])+
                dis[c[i]][d[i+1]]*(1.0-p[i])*p[i+1]+dis[d[i]][c[i+1]]*p[i]*(1.0-p[i+1])+dis[d[i]][d[i+1]]*p[i]*p[i+1]);
            }
        double ans=2147483647;
        for (int i=0;i<=m;i++)
            for (int j=0;j<=min(1,i);j++) ans=min(ans,f[n][i][j]);
        printf("%.2lf",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    HDU4652 Dice
    CF113D Museum / BZOJ3270 博物馆
    SHOI2013 超级跳马
    最基本的卷积与反演
    NOI2014 动物园题解
    SP11414 COT3
    new to do
    linux C++中宏定义的问题:error: unable to find string literal operator ‘operator""fmt’ with ‘const char [4]’, ‘long unsigned int’ arguments
    新装vs2010的问题:fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
    windows下删除虚拟串口的方法,以及解决串口使用中,无法变更设备串口号的问题
  • 原文地址:https://www.cnblogs.com/mastervan/p/11136102.html
Copyright © 2020-2023  润新知