• LOJ2360. 「NOIP2016」换教室【概率DP】【Floyed】【傻逼题】


    LINK


    思路

    先floyed出两点最短路
    然后就可以直接(dp_{i,j,0/1})表示前i节课选择换j节,换不换当前这一节的最小贡献

    直接可以枚举上一次决策的状态计算概率进行统计就可以了


    我变量名写重了僵硬了半天。。。。被安排了


    //Author: dream_maker
    #include<bits/stdc++.h>
    using namespace std;
    //----------------------------------------------
    //typename
    typedef long long ll;
    //convenient for
    #define fu(a, b, c) for (int a = b; a <= c; ++a)
    #define fd(a, b, c) for (int a = b; a >= c; --a)
    #define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
    //inf of different typename
    const int INF_of_int = 1e9;
    const ll INF_of_ll = 1e18;
    //fast read and write
    template <typename T>
    void Read(T &x) {
      bool w = 1;x = 0;
      char c = getchar();
      while (!isdigit(c) && c != '-') c = getchar();
      if (c == '-') w = 0, c = getchar();
      while (isdigit(c)) {
        x = (x<<1) + (x<<3) + c -'0';
        c = getchar();
      }
      if (!w) x = -x;
    }
    template <typename T>
    void Write(T x) {
      if (x < 0) {
        putchar('-');
        x = -x; 
      }
      if (x > 9) Write(x / 10);
      putchar(x % 10 + '0');
    }
    //----------------------------------------------
    const int N = 2010;
    const int M = 310;
    double g[M][M], p[N];
    double dp[N][N][2];
    int c[N], d[N];
    int n, m, v, e;
    int main() {
      Read(n), Read(m), Read(v), Read(e);
      fu(i, 1, n) Read(c[i]);
      fu(i, 1, n) Read(d[i]);
      fu(i, 1, n) scanf("%lf", &p[i]);
      fu(i, 1, v) 
        fu(j, 1, v) g[i][j] = 1e8;
      fu(i, 1, e) {
        int x, y; double w;
        Read(x), Read(y); scanf("%lf", &w);
        g[x][y] = g[y][x] = min(w, g[x][y]);
      }
      fu(i, 1, v) g[i][i] = 0.0;
      fu(k, 1, v)
        fu(i, 1, v) if (i != k)
          fu(j, 1, v) if (j != k)
            g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
      double ans = 1e8;
      fu(i, 1, n)
        fu(j, 0, m) dp[i][j][0] = dp[i][j][1] = 1e8;
      dp[1][0][0] = dp[1][1][1] = 0;
      fu(i, 2, n) {
        fu(j, 0, m) {
          dp[i][j][0] = min(dp[i - 1][j][1] + p[i - 1] * g[d[i - 1]][c[i]] + (1.0 - p[i - 1]) * g[c[i - 1]][c[i]], dp[i - 1][j][0] + g[c[i - 1]][c[i]]);
          if (j) dp[i][j][1] = min(dp[i - 1][j - 1][1] + p[i - 1] * p[i] * g[d[i - 1]][d[i]] + (1.0 - p[i - 1]) * p[i] * g[c[i - 1]][d[i]] + p[i - 1] * (1.0 - p[i]) * g[d[i - 1]][c[i]] + (1.0 - p[i - 1]) * (1.0 - p[i]) * g[c[i - 1]][c[i]], dp[i - 1][j - 1][0] + (p[i] * g[c[i - 1]][d[i]] + (1.0 - p[i]) * g[c[i - 1]][c[i]])); 
        }
      } 
      fu(i, 0, m) ans = min(ans, min(dp[n][i][0], dp[n][i][1]));
      printf("%.2lf", ans);
      return 0;
    }
    
  • 相关阅读:
    HTTP状态码及其含义
    c和python解决各种字符串反转问题的不同思路
    Python找出一串字符中出现最多的字符
    3个基本算法的实现技巧
    一种字符串搜索方法
    数据库开发经典总结
    apt、dpkg参数整理
    Python集合(set)类型的操作
    Python和Decorator(装饰器)模式
    Git使用基础
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9784656.html
Copyright © 2020-2023  润新知