• CH5102 Mobile Service


    CH5102/SP703

    ​ 线性DP状态化简好题

    ​ 根据题意,我们可以设已经完成了 $i - 1$ 个请求现在转移到完成第 $i$ 个为状态,我们发现,如果仅仅只知道完成了请求而不知道三个员工的位置是无法计算代价的,所以不妨再设 $x, y, z$ 为三个员工的状态。

    ​ 此时我们有:

    ​ 设 $ f[i,x,y,z] $ 表示完成了前 $i$ 个请求三个员工分别在 $x,y,z$ 的最小代价

    ​ 观察数据范围,$200^3 * 1000$ 的数据范围是要T掉的,所以继续考虑优化

    ​ 我们考虑,总有一个员工应该在 $p_i$ 的位置,那么我们只需要知道其他两个员工的位置即可,不妨直接设其他两个员工在 $x, y$ , 所以状态转变成:

    ​ 设 $f[i,x,y]$ 表示完成了前 $i$ 个请求时一定有一个员工在 $p_i$ ,其他两个员工分别在 $x,y$ 的位置时的最小代价

    ​ 可以很顺利地写出方程:

    $f[i + 1,x,y] = min(f[i + 1, x, y], f[i,x,y] + c[p_i][p_{i + 1}])$

    $f[i + 1,p_i,y] = min(f[i + 1, p_i, y], f[i,x,y] + c[x][p_{i + 1}])$

    $f[i + 1,x,p_i] = min(f[i + 1, x, p_i], f[i,x,y] + c[y][p_{i + 1}])$

    ​ 起始位置:$p_0 = 3$, 初始值:$f[0,1,2] = 0$,目标:$minleft{ f[n][?][?] ight}$

    ​ 还要注意判断位置的合法性

    Code

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int SIZE = 1000 + 5;
     5 const int inf = 0x7f;
     6 
     7 int n, m;
     8 int a[210][210], p[SIZE], f[SIZE][210][210];
     9 
    10 inline int read()
    11 {
    12   char ch = getchar();
    13   int f = 1, x = 0;
    14   while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    15   while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + ch - '0'; ch = getchar(); }
    16   return x * f;
    17 }
    18 
    19 int main()
    20 {
    21   int t = read();
    22   while (t--)
    23   {
    24     n = read(), m = read();
    25     for (int i = 1; i <= n; i++)
    26       for (int j = 1; j <= n; j++)
    27         a[i][j] = read();
    28     for (int i = 1; i <= m; i++)
    29     p[i] = read();
    30     memset(f, 0x7f, sizeof(f));
    31     f[0][1][2] = 0, p[0] = 3;
    32     for (int i = 0; i < m; i++)
    33     for (int x = 1; x <= n; x++)
    34       for (int y = 1; y <= n; y++)
    35       {
    36         int z = p[i];
    37         if (x == z || y == z || x == y) continue;
    38         if (x != p[i + 1] && y != p[i + 1])
    39           f[i + 1][x][y] = std::min(f[i + 1][x][y], f[i][x][y] + a[z][p[i + 1]]);
    40         if (z != p[i + 1] && x != p[i + 1])
    41            f[i + 1][x][z] = std::min(f[i + 1][x][z], f[i][x][y] + a[y][p[i + 1]]);
    42         if (y != p[i + 1] && z != p[i + 1])
    43             f[i + 1][y][z] = std::min(f[i + 1][y][z], f[i][x][y] + a[x][p[i + 1]]);
    44       }
    45     int ans = 0x7f7f7f7f;
    46     for (int i = 1; i <= n; i++)
    47       for (int j = 1; j <= n; j++)
    48         ans = std::min(ans, f[m][i][j]);
    49     printf("%d
    ", ans);
    50   }
    51   return 0;
    52 }
  • 相关阅读:
    SQL中的聚合函数
    vs移动团队项目集合
    网页变量的赋值示例
    PRD、MRD、BRD的含义
    w3cschool中jQuery测试结果总结
    sql队伍的胜负情况
    winform中获取当前周次
    select2 的使用
    layui layer table 常见问题
    spring websocket tomcat was websphere9.0 Multiple Endpoints may not be deployed to the same path
  • 原文地址:https://www.cnblogs.com/Tony102/p/11218793.html
Copyright © 2020-2023  润新知