zoukankan      html  css  js  c++  java
  • 「Luogu」1850 换教室 (期望dp)

    题意:原题在这

    Little Yu的n个时间段上都有两节课同时进行,她一开始在dflt[i]教室,想去hope[i]教室,而申请通过概率为k[i],且总共有m次机会可以申请。

    已知Yu的学校有v个教室,e条道路相互连通(无向图),每条路有一个代价。
    求:申请哪几门课程能使Yu在教室之间乱跑的体力期望最小

    做法:(详见行内注释)

    1. dp[i][j][k]表示到第i个点,已经更改了j次,k=0这个点不更,k=1这个点更 的最小期望

    2. memset不能初始化最大值会爆炸

    3. dp转移方程过于麻烦详见代码注释

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define inf 999999999
    #define maxm 305
    #define maxn 2005
    using namespace std;
    int n,m,v,e;
    double ans=inf;//一定要是inf,不能是0
    int dflt[maxn],hope[maxn];//原教室和想去的教室
    double dp[maxn][maxn][2],dis[maxm][maxm];
    double k[maxn];//换教室的概率
    
    void input()
    {
        cin>>n>>m>>v>>e;
        for(int i=1;i<=n;i++) cin>>dflt[i];
        for(int i=1;i<=n;i++) cin>>hope[i];
        for(int i=1;i<=n;i++) cin>>k[i];
    
        for(int i=1;i<=v;i++)
        for(int j=1;j<i;j++)
        {
            dis[i][j]=inf;
            dis[j][i]=inf;
        }
        for(int i=1;i<=e;i++)
        {
            int f,g;double w;
            cin>>f>>g>>w;
            dis[f][g]=min(dis[f][g],w);
            dis[g][f]=dis[f][g];
        }
        
        for(int k=1;k<=v;k++)//Floyd跑一发两个教室间的距离
        for(int i=1;i<=v;i++)
        for(int j=1;j<i;j++)
        {
            if(dis[i][j]>dis[i][k]+dis[k][j])
            {
                dis[i][j]=dis[i][k]+dis[k][j];
                dis[j][i]=dis[i][j];
            }
        }
        return;
    }
    
    int main()
    {
        input();
        for(int i=1;i<=n;i++)
        for(int j=0;j<=m;j++)
        for(int k=0;k<=1;k++)
        {
            dp[i][j][k]=inf; 
        }
    //     memset(dp,inf,sizeof(dp));
        dp[1][0][0]=0.0;dp[1][1][1]=0.0;
        
        for(int i=2;i<=n;i++)
        for(int j=0;(j<=m)&&(j<=i);j++)
        {
            dp[i][j][0]=min(dp[i-1][j][0]+dis[dflt[i-1]][dflt[i]],
          //这个点不换:     上个点也不换
            dp[i-1][j][1]+dis[dflt[i-1]][dflt[i]]*(1-k[i-1])+dis[hope[i-1]][dflt[i]]*k[i-1]);
            //上个点没换成                                    上个点换了
            
            if(j>=1)
            {
                dp[i][j][1]=min(dp[i-1][j-1][0]+dis[dflt[i-1]][hope[i]]*k[i]+dis[dflt[i-1]][dflt[i]]*(1.0-k[i]),
                //这个点要换:   上个点没换       这个点换了                    这个点没换成
                dp[i-1][j-1][1]+dis[hope[i-1]][hope[i]]*k[i-1]*k[i]+
                //上个点和这个点都换了
                dis[hope[i-1]][dflt[i]]*k[i-1]*(1.0-k[i])+
                //上个点换了,这个点没换成
                dis[dflt[i-1]][hope[i]]*(1.0-k[i-1])*k[i]+
                //上个点没换,这个点换成了
                dis[dflt[i-1]][dflt[i]]*(1.0-k[i-1])*(1.0-k[i]));
                //两个点都没换
            }
        }
        
        for(int i=0;i<=m;i++)
        for(int j=0;j<=1;j++)
        {
            ans=min(ans,dp[n][i][j]);
        }
        printf("%.2lf",ans);
        return 0;
    }
  • 相关阅读:
    让一个 csproj 项目指定多个开发框架
    推荐近乎免费的调试神器——OzCode
    再也不用克隆多个仓库啦!git worktree 一个 git 仓库可以连接多个工作目录
    .NET Core 和 .NET Framework 中的 MEF2
    将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件
    .NET 中的轻量级线程安全
    卡诺模型(KANO Model)
    C#/.NET 匿名函数会捕获变量,并延长对象的生命周期
    迫不及待地体验了一把 C#8.0 中的可空引用类型(Nullable Reference)
    异步任务中的重新进入(Reentrancy)
  • 原文地址:https://www.cnblogs.com/LocaEtric/p/9614305.html
Copyright © 2011-2022 走看看