• 【BZOJ4720】【NOIP2016】换教室 [期望DP]


    换教室

    Time Limit: 20 Sec  Memory Limit: 512 MB
    [Submit][Status][Discuss]

    Description

    Input

      第一行四个整数n,m,v,e。n表示这个学期内的时间段的数量;m表示牛牛最多可以申请更换多少节课程的教室;
      v表示牛牛学校里教室的数量;e表示牛牛的学校里道路的数量。
      第二行n个正整数,第i(1≤i≤n)个正整数表示c,,即第i个时间段牛牛被安排上课的教室;保证1≤ci≤v。
      第三行n个正整数,第i(1≤i≤n)个正整数表示di,即第i个时间段另一间上同样课程的教室;保证1≤di≤v。
      第四行n个实数,第i(1≤i≤n)个实数表示ki,即牛牛申请在第i个时间段更换教室获得通过的概率。保证0≤ki≤1。
      接下来e行,每行三个正整数aj,bj,wj,表示有一条双向道路连接教室aj,bj,通过这条道路需要耗费的体力值是Wj;
      保证通过学校里的道路,从任何一间教室出发,都能到达其他所有的教室。
      保证输入的实数最多包含3位小数。

    Output

      输出一行,包含一个实数,四舎五入精确到小数点后恰好2位,表示答案。你的
      输出必须和标准输出完全一样才算正确。

    Sample Input

      3 2 3 3
      2 1 2
      1 2 1
      0.8 0.2 0.5
      1 2 5
      1 3 3
      2 3 1

    Sample Output

      2.80

    HINT

      1≤aj,bj≤v, 1≤wj≤100。
      1≤n≤2000, 0≤m≤2000, 1≤v≤300, 0≤e≤90000。

    Main idea

      给定n个 原本教室ci 和 替换教室di,可以申请m次换课,如果 i 换课了则可以在di上课,否则在ci上课,每个教室之间有距离,求期望最小距离。

    Solution

      很简单的期望DP,我们令 f[i][j][01] 表示 到了第 i 个状态,已经换了 j 次课,这次换不换课,然后分四种情况讨论一下即可。

    Code

    #include<iostream>    
    #include<string>    
    #include<algorithm>    
    #include<cstdio>    
    #include<cstring>    
    #include<cstdlib>
    #include<cmath>
    using namespace std;  
     
    #define Road(a,b) (double)w[a][b]
    #define tense(a,b) a = a<b ? a:b;
     
    const int ONE = 2005;
    const double INF = 1e18;
     
    int n,m,v,e;
    int x,y,z;
    int c[ONE],d[ONE];
    int w[301][301];
    double f[ONE][ONE][2],k[ONE];
    double Ans;
     
    int get()
    {    
            int res=1,Q=1;char c;    
            while( (c=getchar())<48 || c>57 ) 
            if(c=='-')Q=-1; 
            res=c-48;     
            while( (c=getchar())>=48 && c<=57 )    
            res=res*10+c-48;    
            return res*Q;    
    }
     
    void Floyed()
    {
            for(int k=1; k<=v; k++)
            for(int i=1; i<=v; i++)
            for(int j=1; j<=v; j++)
                tense(w[i][j], w[i][k] + w[k][j]);
    }
     
    double Eap10(int i)
    {
            return Road( c[i],c[i+1] ) * (1-k[i]) + Road( d[i],c[i+1] ) * k[i];
    }
    
    double Eap01(int i)
    {
            return Road( c[i],c[i+1] ) * (1-k[i+1]) + Road( c[i],d[i+1] ) * k[i+1];
    }
    
    double Eap11(int i)
    {
            return 
                Road( c[i], c[i+1] ) * (1-k[i]) * (1-k[i+1]) 
              + Road( c[i], d[i+1] ) * (1-k[i]) * k[i+1]
              + Road( d[i], c[i+1] ) * k[i] * (1-k[i+1])
              + Road( d[i], d[i+1] ) * k[i] * k[i+1]; 
    }
    
    void DisApply(int i,int j)
    { 
            if(j>=0) f[i+1][j][0] = tense(f[i+1][j][0], f[i][j][0] + Road( c[i],c[i+1] ) );
            if(j>=1) f[i+1][j][0] = tense(f[i+1][j][0], f[i][j][1] + Eap10(i) );
    }
     
    void Apply(int i,int j)
    {
            if(j>=1) f[i+1][j][1] = tense(f[i+1][j][1], f[i][j-1][0] + Eap01(i) );
            if(j>=2) f[i+1][j][1] = tense(f[i+1][j][1], f[i][j-1][1] + Eap11(i) );
    }
    
    int main()  
    {    
            n = get();  m = get();  v = get();  e = get();
            for(int i=1; i<=n; i++) c[i] = get();
            for(int i=1; i<=n; i++) d[i] = get();
            for(int i=1; i<=n; i++) scanf("%lf", &k[i]);
             
            memset(w, 1, sizeof(w));
            for(int i=1; i<=v; i++) w[i][i] = 0;
            for(int i=1; i<=e; i++)
            {
                x = get();  y = get();  z = get();
                w[x][y] = min(w[x][y], z);
                w[y][x] = min(w[y][x], z);
            }
            Floyed();
             
            for(int i=1; i<=n; i++)
                for(int j=0; j<=m; j++)
                    f[i][j][0] = f[i][j][1] = INF;
            f[1][0][0] = f[1][1][1] = 0;
            
            for(int i=1; i<=n-1; i++)
                for(int j=0; j<=m; j++)
                    DisApply(i,j), Apply(i,j);
             
            Ans = INF;
            for(int j=0; j<=m; j++)
            {
                tense(Ans, f[n][j][0]);
                tense(Ans, f[n][j][1]);
            }
             
            printf("%.2lf",Ans);
    }
    View Code
  • 相关阅读:
    php---观察者模式
    elasticsearch常用查询和注意点
    linux镜像iso格式
    Mysql查询今天、昨天、7天、近30天、本月、上一月数据
    php常用算法
    算法之斐波纳契数列递归和迭代实现
    带你了解session和cookie作用原理区别和用法
    mysql大数据量的分页优化
    常用链接
    自然语言处理
  • 原文地址:https://www.cnblogs.com/BearChild/p/6863350.html
Copyright © 2020-2023  润新知