• bzoj4720 / P1850 换教室(Floyd+期望dp)


    P1850 换教室

    先用Floyd把最短路处理一遍,接下来就是重头戏了

    用 f [ i ][ j ][ 0/1 ] 表示在第 i 个时间段,发出了 j 次申请(注意不一定成功),并且在这个时间段是否(1/0)申请换了教室

    需要知道的一点是:既然是期望,我们求的就是边权*概率(P4316 绿豆蛙的归宿)的和

    同样的,在这题中,我们需要求的是,可转移的状态(d [ i ][ j ])*概率之和

    既然是求最小期望,那么我们只要求从第 1->n 个时间段中可以转移的最短(期望)路径,统计这条路径上的期望即可

    所以列出状态转移方程(详见代码),解决qwq

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    using namespace std;
    inline int Int(){
        char c=getchar(); int x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
        return x;
    }
    inline int min1(const int &a,const int &b) {return a<b? a:b;}
    inline double min2(const double &a,const double &b) {return a<b ?a:b;}
    
    int n,m,v,e,a[2002],b[2002],d[302][302];
    double c[2002],f[2002][2002][2];
    
    int main(){
        n=Int(); m=Int(); v=Int(); e=Int();
        for(int i=1;i<=n;++i) a[i]=Int();
        for(int i=1;i<=n;++i) b[i]=Int();
        for(int i=1;i<=n;++i) scanf("%lf",&c[i]);
    
        memset(d,63,sizeof(d));
        int q1,q2,q3;
        for(int i=1;i<=e;++i){
            q1=Int(); q2=Int(); q3=Int();
            d[q1][q2]=d[q2][q1]= d[q1][q2]<q3 ? d[q1][q2]:q3;
        }
        for(int k=1;k<=v;++k)
            for(int i=1;i<=v;++i)
                for(int j=1;j<=v;++j)
                    d[i][j]=min1(d[i][j],d[i][k]+d[k][j]);
        for(int i=1;i<=v;++i) d[i][i]=0; 
    //Floyd最短路
    for(int i=1;i<=n;++i) for(int j=0;j<=m;++j) f[i][j][0]=f[i][j][1]=100000000; f[1][0][0]=f[1][1][1]=0; for(int i=2;i<=n;++i) //对于每一种状态进行转移:找到一种期望最小、可以转移过来的状态 { f[i][0][0]=f[i-1][0][0]+d[a[i-1]][a[i]]; for(int j=1;j<=m;++j) { f[i][j][0]=min2(f[i][j][0],f[i-1][j][0] +(double)d[a[i-1]][a[i]]); //这次和上次都不申请 f[i][j][0]=min2(f[i][j][0],f[i-1][j][1] +(double)d[b[i-1]][a[i]]*c[i-1] //这次不申请,上次申请成功 +(double)d[a[i-1]][a[i]]*(1.0-c[i-1])); //这次不申请,上次申请失败 f[i][j][1]=min2(f[i][j][1],f[i-1][j-1][0] +(double)d[a[i-1]][b[i]]*c[i] //这次申请成功,上次不申请 +(double)d[a[i-1]][a[i]]*(1.0-c[i])); //这次申请失败,上次不申请 f[i][j][1]=min2(f[i][j][1],f[i-1][j-1][1] +(double)d[b[i-1]][b[i]]*c[i-1]*c[i] //这次和上次都申请成功 +(double)d[a[i-1]][b[i]]*(1.0-c[i-1])*c[i] //这次申请成功,上次申请失败 +(double)d[b[i-1]][a[i]]*c[i-1]*(1.0-c[i]) //这次申请失败,上次申请成功 +(double)d[a[i-1]][a[i]]*(1.0-c[i-1])*(1.0-c[i])); //这次和上次都申请失败 } } double ans=100000000.00; for(int i=0;i<=m;++i) ans=min2(ans,min2(f[n][i][0],f[n][i][1])); //扫一遍找最小期望 printf("%.2lf",ans); return 0; }
  • 相关阅读:
    HDU 1594 find the max
    mongoose 数据库操作2
    我也来开发2048之终极奥义
    cocos2d-x 2.2.0 怎样在lua中注冊回调函数给C++
    windows常用运行命令
    机器学习——Pandas库
    搭建靶场环境
    Ubuntu快速安装MSF
    docker 基本使用
    linux下杀死进程
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9543195.html
Copyright © 2020-2023  润新知