zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    自动化测试用例设计实例
    day07 python2与python3 编码
    day06-2 数据结构
    遇到一个关于C#调用Microsoft.Office.Interop.Word实例化的一个问题
    关于C#调用matlab生成的dll的一些经验(亲测)
    javascript 检测浏览类型和版本
    图片自适应完美兼容IE8
    Java VS .NET:Java与.NET的特点对比
    【C#点滴记录】ASP.NET 使用C# 导出Word 和Excel
    关于现在IT行业从业者一些建议
  • 原文地址:https://www.cnblogs.com/Tony102/p/11218793.html
Copyright © 2011-2022 走看看