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

    题面

    太长了,不想粘,就甩个链接吧

    Link

    题解

    这个题就是转移方程的分类讨论麻烦了些,其他的没什么。

    首先,我们要利用 Floyd 求出每两个点之间的距离 (n的范围那么小,肯定是Floyed 啦

    我们就要考虑怎么 dp

    我们设 (f[i][j][0/1]) 表示 处理完前 (i) 门课,用了 (j) 次申请,且最后一门课换或者没换的概率。

    然后我们就要开始大力讨论。

    1. 这次上课没换的期望值

    1.上次也没换,期望值就是 f[i-1][j][0] + dis[a[i-1]][[a[i]]

    2.上次换了但没通过,他的概率是 1-p[i-1] 期望值就是 dis[a[i-1]][a[i]] * (1-p[i-1])

    3.上次换了且通过了, 他的概率是 p[i-1] 期望值就是 p[i-1] * dis[b[i-1]][a[i]]

    第二种和第三种情况和在一起就是 f[i-1][j][1] + p[i-1] * dis[b[i-1]][a[i]] + (1-p[i-1]) * dis[a[i-1]][a[i]]

    这样,我们就得到了这次不换的转移方程

    f[i][j][0] = min(f[i-1][j][0] + 1.0 * dis[a[i-1]][a[i]], f[i-1][j][1] + p[i-1] * dis[b[i-1]][a[i]] + (1-p[i-1]) * dis[a[i-1]][a[i]]);
    
    
    2.这次要换的期望

    上次没换,这次换了没通过的情况 他的概率是 (1-p[i]) 期望就是 (1-p[i]) * dis[a[i-1]][a[i]]

    上次没换,这次换了通过的情况,他的概率是 p[i],期望值是 p[i] * dis[a[i-1]][b[i]]

    上次换了没通过,这次换了也没通过的情况,概率为 (1-p[i-1]) * (1-p[i]) 期望值就是 (1-p[i-1]) * (1-p[i]) * dis[a[i-1]][a[i]]

    上次换了没通过,这次换了通过的情况,概率为 (1-p[i-1]) * p[i] 期望值为 (1-p[i-1]) * p[i] * dis[a[i-1]][b[i]]

    上次换了通过了,这次换了没通过的情况,概率为 p[i-1] * (1-p[i]) 期望值为 p[i-1] * (1-p[i]) * dis[b[i-1]][a[i]]

    上次换了通过了,这次换了也通过的情况,概率为 p[i-1] * p[i] 期望值为 p[i] * p[i-1] * dis[b[i-1]][b[i]]

    然后,前两种情况可以合并在一起由 f[i-1][j-1][0] 转移过来,后四种情况可以合并在一起,由 f[i-1][j-1][1] 转移过来。

    具体方程长这样

    f[i][j][1] = min(f[i-1][j-1][0] + p[i] * dis[a[i-1]][b[i]] + (1-p[i]) * dis[a[i-1]][a[i]],
                     f[i-1][j-1][1] + p[i] * p[i-1] * dis[b[i-1]][b[i]] + (1-p[i-1]) * (1-p[i]) * dis[a[i-1]][a[i]] + p[i-1] * (1-p[i]) * dis[b[i-1]][a[i]] + (1-p[i-1]) * p[i] * dis[a[i-1]][b[i]]);
    

    初始化

    f[1][0][0] = f[1][1][1] = 0.0, 其他都为极大值。

    因为 1 是起点,从那边开始都是一样的

    转移时注意 (j) 的边界 要特判一下 j == 0 的情况,我就因为这个交了好几遍

    Code:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m,v,e,x,y,z,w,a[2010],b[2010],dis[310][310];
    double p[2010],f[2010][2010][2],ans = 2333333.0;
    inline int read()
    {
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){s =s * 10+ch - '0'; ch = getchar();}
        return s * w;
    }
    int main()
    {
        n = read(); m = read(); v = read(); e = read();
        for(int i = 1; i <= n; i++) a[i] = read();
        for(int i = 1; i <= n; i++) b[i] = read();
        for(int i = 1; i <= n; i++) scanf("%lf",&p[i]);
        for(int i = 1; i <= v; i++)
        {
            for(int j = 1; j <= v; j++)
            {
                if(i == j) dis[i][j] = 0;
                else dis[i][j] = 23333333;
            } 
        }
        for(int i = 1; i <= e; i++) 
        {
            x = read(); y = read(); w = read();
            dis[x][y] = min(dis[x][y],w);//解决重边问题
            dis[y][x] = min(dis[y][x],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] = min(dis[i][j],dis[i][k]+dis[k][j]);
                }
            }
        }
        for(int i = 1; i <= n; i++) 
        {
        	for(int j = 0; j <= m; j++)
        	{
        		f[i][j][0] = f[i][j][1] = 2333333.0;
        	}
        }
        f[1][0][0] = f[1][1][1] = 0.0;
        for(int i = 2; i <= n; i++)
        {
            for(int j = 0; j <= m; j++)
            {
                f[i][j][0] = min(f[i-1][j][0] + 1.0 * dis[a[i-1]][a[i]], f[i-1][j][1] + p[i-1] * dis[b[i-1]][a[i]] + (1-p[i-1]) * dis[a[i-1]][a[i]]);
                if(j != 0) f[i][j][1] = min(f[i-1][j-1][0] + p[i] * dis[a[i-1]][b[i]] + (1-p[i]) * dis[a[i-1]][a[i]],f[i-1][j-1][1] + p[i] * p[i-1] * dis[b[i-1]][b[i]] + (1-p[i-1]) * (1-p[i]) * dis[a[i-1]][a[i]] + p[i-1] * (1-p[i]) * dis[b[i-1]][a[i]] + (1-p[i-1]) * p[i] * dis[a[i-1]][b[i]]);
            } 
        }
        for(int i = 0; i <= m; i++) ans = min(ans,min(f[n][i][1],f[n][i][0]));//他申请次数可以不用完
        printf("%.2lf",ans);
        return 0;
    }
    
  • 相关阅读:
    vue element-ui,上传文件加载进度条显示效果(使用定时器实现源码分享)
    vue element-ui 上传文件的 :on-progress钩子无法触发的原因及报错原因
    vue打包文件后首次加载速度慢解决方法----1.压缩文件js.css 2.使用cdn加载
    vue 报错 RangeError: Maximum call stack size exceeded
    vue在IE11报错‘vuex requires a Promise polyfill in this browser.’
    轻松理解MYSQL MVCC 实现机制
    推荐:mysql锁 innodb下的记录锁,间隙锁,next-key锁
    MySQL的四种事务隔离级别
    php中文件上传大小限制如何修改
    Https原理及流程
  • 原文地址:https://www.cnblogs.com/genshy/p/13605510.html
Copyright © 2011-2022 走看看