zoukankan      html  css  js  c++  java
  • P1850 换教室 题解

    题目链接:-----

    题意:

    有 v 间教室, 教室之间有 e 条双向边连接, 从一个教室走到另一个教室需要一
    定时间. 有 n 节课, 第 i 节课有两间教室, 默认要去第 c[i] 间教室, 可以申请到
    第 d[i] 间教室去, 申请通过的概率为 p[i], 所有申请必须在最开始提交. 求出提
    交申请个数不超过 m 的情况下, 依次上完这 n 节课期望最少要走多远.
    v ≤ 300, e ≤ 90000, n ≤ 2000.

    前置知识:

    1.全概率公式:

    P(A)=sum_{i=1}^{n} {P(A|Bi)*P(Bi)}

    2.随机变量是在概率空间的基本变量上定义的函数.
    记 E(X) 为随机变量 X 的期望值

    E(X)=sum_{w=1}^{n} {P(w)*X(w)}

    可以看做概率乘以权值。

    3.期望具有线性性:

    E(aX + Y ) = aE(X) + E(Y )

    题解思路:

    每节课之间要走的路程的期望之和可以根据期望的线性性,

    求出每一个路程的期望,累加即可。

    1.先用floyd求出最短路。

    2.f[i][j][0/1]表示上完第I节课后,用了j次申请,第i节课是否换教室,期望路程的最小值。

    3.因为它只是期望,如果有期望得到申请,也得加上期望没有得到申请的情况。

    4.转移方程比较恶心,我就不贴了。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define ll long long 
    #define R register
    using namespace std;
    const int N=2005;
    const int M=2005;
    const int INF=200000000;
    //14299.96
    //f[i][j][0/1]  到第i节课  用了 j 个 申请 第i节课换不换的期望
    int n,m,v,e,c[N],d[N],far[M][M];
    double f[N][N][2],k[N],ans=INF;
    int main(){
        scanf("%d%d%d%d",&n,&m,&v,&e);//时间 次数 点数 边数
        for(R int i=1;i<=n;i++)
        scanf("%d",&c[i]);//不换
        for(R int i=1;i<=n;i++)
        scanf("%d",&d[i]);//
        for(R int i=1;i<=n;i++)
        scanf("%lf",&k[i]);//概率
    
        for(R int i=1;i<=v;i++)
        for(R int j=1;j<=v;j++)
        far[i][j]=INF;
        for(R int i=1;i<=e;i++)
        {
            R int u,v;
            R int w;
            scanf("%d%d%d",&u,&v,&w);
            far[u][v]=min(w,far[u][v]);
            far[v][u]=min(w,far[v][u]);
        }
    
        for(R int i=1;i<=v;i++)
        far[i][i]=0;
    
        for(R int t=1;t<=v;t++)
        for(R int i=1;i<=v;i++)
        for(R int j=1;j<=v;j++)
        far[i][j]=min(far[i][j],far[i][t]+far[t][j]);
    
        for(R int i=1;i<=n;i++)
        for(R int j=0;j<=m;j++)
        for(R int t=0;t<=1;t++)
        f[i][j][t]=INF;
        
        f[1][0][0]=0;
        f[1][1][1]=0;
        for(R int i=2;i<=n;i++)
        {
            for(R int j=0;j<=min(m,i);j++)
            {
            if(j<=i-1)
            f[i][j][0]=min(
            f[i-1][j][0]+
            far[c[i-1]][c[i]],
            
            f[i-1][j][1]+
            far[d[i-1]][c[i]]*k[i-1]+
            far[c[i-1]][c[i]]*(1-k[i-1]));
            
            if(j!=0)
            f[i][j][1]=min(
            f[i-1][j-1][0]+
            far[c[i-1]][d[i]]*k[i]+
            far[c[i-1]][c[i]]*(1-k[i]),
            
            f[i-1][j-1][1]+
            far[d[i-1]][d[i]]*k[i]*k[i-1]+
            far[c[i-1]][d[i]]*(1-k[i-1])*k[i]+
            far[d[i-1]][c[i]]*(1-k[i])*k[i-1]+
            far[c[i-1]][c[i]]*(1-k[i])*(1-k[i-1]));
            }
        }
        for(R int i=0;i<=m;i++){
            if(i<=n-1)
            ans=min(ans,f[n][i][0]);
            if(i!=0)
            ans=min(ans,f[n][i][1]);
        }
        printf("%.2lf",ans);
        return 0;
    }
  • 相关阅读:
    在Windows 10 64位上编译DCMTK
    python递归解决汉诺塔
    python迭代和递归实现斐波那契
    20199302 2019-2020-2 《网络攻防实践》第4周作业
    ssh爆破
    20199302 2019-2020-2 《网络攻防实践》第3周作业
    字符串模版替换的方法MessageFormat.format(String pattern, Object ... arguments)
    Java并发编程之LinkedBlockingDeque阻塞队列详解
    理解Spring容器、BeanFactory和ApplicationContext
    Steam之两个list间交集、并集、差集
  • 原文地址:https://www.cnblogs.com/sky-zxz/p/9882481.html
Copyright © 2011-2022 走看看