zoukankan      html  css  js  c++  java
  • 计蒜客 T2033 换教室

    题目链接:计蒜客 T2033 换教室

    题目大意:

    题解:
    膜拜出题人!!!状态转移方程写到吐血。。。
    膜拜出题人!!!状态转移方程写到吐血。。。
    膜拜出题人!!!状态转移方程写到吐血。。。

    首先通过(Floyd)计算所有教室间的最短距离。

    (dp[i][j][0/1])表示前(i)节课申请了(j)次,第(i)节课是否申请的情况下耗费体力的期望的最小值。

    一、首先考虑第(i)节课不申请的情况:

    从两种情况转移而来:

    1. 上一节课没申请换课,那么课间从(c[i-1])走到(c[i])
    2. 上一节课申请换课了:
      (1) 申请通过,那么课间从(d[i-1])走到(c[i])
      (2) 申请没通过,那么课间从(c[i-1])走到(c[i])

    状态转移方程为:

    [dp[i][j][0]=min{dp[i][j][0],dp[i−1][j][0]+dis[c[i−1]][c[i]],dp[i−1][j][1]+(1−p[i−1])∗dis[c[i−1]][c[i]]+p[i−1]∗dis[d[i−1]][c[i]]} ]

    二、再考虑第(i)节课申请的情况:

    还是从两种情况转移而来:

    1. 上一节课没申请换课:
      (1) 这节课申请通过,那么课间从(c[i-1])走到(d[i])
      (2) 这节课申请没通过,那么课间从(c[i-1])走到(c[i])
    2. 上一节课申请换课了:
      (1) 上节课申请通过,这节课申请通过,那么课间从(d[i-1])走到(d[i])
      (2) 上节课申请没通过,这节课申请通过,那么课间从(c[i-1])走到(d[i])
      (3) 上节课申请通过,这节课申请没通过,那么课间从(d[i-1])走到(c[i])
      (4) 上节课申请没通过,这节课申请没通过,那么课间从(c[i-1])走到(c[i])

    状态转移方程为:

    [dp[i][j][1]=min{dp[i][j][1],dp[i−1][j−1][0]+p[i]∗dis[c[i−1]][d[i]]+(1−p[i])∗dis[c[i−1]][c[i]],dp[i−1][j−1][1]+p[i−1]∗p[i]∗dis[d[i−1]][d[i]]+p[i−1]∗(1−p[i])∗dis[d[i−1]][c[i]]+(1−p[i−1])∗p[i]∗dis[c[i−1]][d[i]]+(1−p[i−1])∗(1−p[i])∗dis[c[i−1]][c[i]]} ]

    #include <iomanip>
    #include <iostream>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define N 2010
    #define M 310
    
    double p[N], dis[M][M], dp[N][N][2];
    int c[N], d[N], n, m, v, e;
    
    int main() {
        ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
        cin >> n >> m >> v >> e;
        for (int i = 1; i <= n; ++i) {
            cin >> c[i];
        }
        for (int i = 1; i <= n; ++i) {
            cin >> d[i];
        }
        for (int i = 1; i <= n; ++i) {
            cin >> p[i];
        }
        for (int i = 1; i <= v; ++i) {
            for (int j = 1; j <= v; ++j) {
                dis[i][j] = INF;
            }
        }
        for (int i = 1; i <= v; ++i) {
            dis[i][i] = 0;
        }
        for (int i = 1; i <= e; ++i) {
            int x, y;
            double z;
            cin >> x >> y >> z;
            dis[x][y] = dis[y][x] = min(dis[x][y], z);
        }
        for (int k = 1; k <= v; ++k) {  // floyd
            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) {
                dp[i][j][0] = dp[i][j][1] = INF;
            }
        }
        dp[1][0][0] = dp[1][1][1] = 0;
        for (int i = 2; i <= n; ++i) {
            for (int j = 0; j <= min(i, m); ++j) {
                dp[i][j][0] = min(dp[i][j][0], dp[i - 1][j][0] + dis[c[i - 1]][c[i]]);
                dp[i][j][0] = min(dp[i][j][0], dp[i - 1][j][1] + (1 - p[i - 1]) * dis[c[i - 1]][c[i]] + p[i - 1] * dis[d[i - 1]][c[i]]);
                if (j) {
                    dp[i][j][1] = min(dp[i][j][1], dp[i - 1][j - 1][0] + p[i] * dis[c[i - 1]][d[i]] + (1 - p[i]) * dis[c[i - 1]][c[i]]);
                    dp[i][j][1] = min(dp[i][j][1], dp[i - 1][j - 1][1] + p[i - 1] * p[i] * dis[d[i - 1]][d[i]] + p[i - 1] * (1 - p[i]) * dis[d[i - 1]][c[i]] + (1 - p[i - 1]) * p[i] * dis[c[i - 1]][d[i]] + (1 - p[i - 1]) * (1 - p[i]) * dis[c[i - 1]][c[i]]);
                }
            }
        }
        double ans = INF;
        for (int i = 0; i <= m; ++i) {
            ans = min(ans, min(dp[n][i][1], dp[n][i][0]));
        }
        cout << fixed << setprecision(2) << ans;
        return 0;
    }
    
  • 相关阅读:
    laravel excel 导入
    linux 怎么解压
    mysql分表和表分区详解
    mysql主从复制windows-》linux
    Redis和Memcache的区别
    mysql group by 用法解析(详细)
    [置顶] mysql常用函数
    mysql测试数据库employees一些sql语句
    session入mysql
    session入库
  • 原文地址:https://www.cnblogs.com/IzumiSagiri/p/15063678.html
Copyright © 2011-2022 走看看