SP703 SERVICE - Mobile Service
SP703 SERVICE - Mobile Service - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
容易想到状态 \(f(i, x, y, z)\) 表示完成了前 \(i\) 个请求,三个员工分别位于 \(x\),\(y\),\(z\) 时,当前最小花费。
发现状态规模达到 \(nL^3\),不能接受。考虑完成前 \(i\) 个请求后一定有一个员工位于 \(p[i]\),因此有一位员工位置信息是冗余的。
更换定义,\(f(i, x, y)\) 表示完成了前 \(i\) 个请求,三个员工分别位于 \(p[i]\),\(x\),\(y\) 时的最小花费。
初始时 \(f\) 应该均置为 \(+\infty\),\(f(0, 2, 3) = 0\),\(p[0] = 1\)。
时间复杂度 \(\mathcal{O}(nL^2)\)。
/*
 * @Author: crab-in-the-northeast 
 * @Date: 2022-11-09 04:32:07 
 * @Last Modified by: crab-in-the-northeast
 * @Last Modified time: 2022-11-09 04:53:57
 */
#include <bits/stdc++.h>
inline int read() {
    int x = 0;
    bool f = true;
    char ch = getchar();
    for (; !isdigit(ch); ch = getchar())
        if (ch == '-')
            f = false;
    for (; isdigit(ch); ch = getchar())
        x = (x << 1) + (x << 3) + ch - '0';
    return f ? x : (~(x - 1));
}
inline bool gmi(int &a, int b) {
    return b < a ? a = b, true : false;
}
const int maxl = 205;
const int maxn = 1005;
int c[maxl][maxl];
int p[maxn];
int f[maxn][maxl][maxl];
int main() {
    int T = read();
    while (T--) {
        int l = read(), n = read();
        std :: memset(f, 0x3f, sizeof(f));
        for (int i = 1; i <= l; ++i)
            for (int j = 1; j <= l; ++j)
                c[i][j] = read();
        for (int i = 1; i <= n; ++i)
            p[i] = read();
        
        p[0] = 1;
        f[0][2][3] = 0;
        for (int i = 0; i <= n; ++i) {
            for (int x = 1; x <= l; ++x) {
                for (int y = 1; y <= l; ++y) {
                    int z = p[i], t = p[i + 1];
                    int fn = f[i][x][y];
                    if (x == y || y == z || x == z)
                        continue;
                    if (x != t && y != t)
                        gmi(f[i + 1][x][y], fn + c[z][t]);
                    if (x != t && z != t)
                        gmi(f[i + 1][x][z], fn + c[y][t]);
                    if (y != t && z != t)
                        gmi(f[i + 1][y][z], fn + c[x][t]);
                }
            }
        }
        int ans = INT_MAX;
        for (int x = 1; x <= l; ++x)
            for (int y = 1; y <= l; ++y)
                if (x != y && x != p[n] && y != p[n])
                    gmi(ans, f[n][x][y]);
        
        printf("%d\n", ans);
    }
    return 0;
}

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号