设计状态F[i][j][k]代表完成任务i后,有一个员工在地点P[i],其他两人分别在j和k两地。所需要的最小代价。
转移的方式:
分别考虑派遣i,j,k三人前往下一个需求地点,并更新状态。
#include <iostream> #include <stdio.h> #include <string.h> #define re register #define GC getchar() #define Clean(X,K) memset(X,K,sizeof(X)) #include <iostream> #define Max(A,B) ((A)>(B)?(A):(B)) #define Min(A,B) ((A)<(B)?(A):(B)) using namespace std ; int Qread () { int X = 0 ; char C = GC ; while (C > '9' || C < '0') C = GC ; while (C >='0' && C <='9') { X = X * 10 + C - '0' ; C = GC ; } return X ; } const int Maxl = 205 , Maxn = 1005 ,INF = 20021020 << 2; int C[Maxl][Maxn] , N , L , Times , Q[Maxn] = {1}, F[Maxn][Maxl][Maxl]; int main () { // freopen ("SP703.in" , "r" , stdin) ; Times = Qread () ; while (Times -- ) { Clean (F , 0) ; L = Qread () , N = Qread () ; for (re int i = 1 ; i <= L; ++ i) for (re int j = 1 ; j <= L; ++ j) C[i][j] = Qread () ; for (re int i = 1 ; i <= N; ++ i) Q[i] = Qread () ; Clean (F , 0x3f) ; F[0][2][3] = 0 ; for (re int i = 0 ; i < N; ++ i) { for (re int j = 1 ; j <= L ; ++ j) { for (re int k = 1 ; k <= L; ++ k) { if (Q[i] == j || Q[i] == k || j == k) continue ; F[i + 1][j][k] = Min (F[i + 1][j][k] ,F[i][j][k] + C[Q[i]][Q[i + 1]]) ; F[i + 1][Q[i]][k] = Min (F[i + 1][Q[i]][k] , F[i][j][k] + C[j][Q[i + 1]]) ; F[i + 1][j][Q[i]] = Min (F[i + 1][j][Q[i]] , F[i][j][k] + C[k][Q[i + 1]]) ; } } } int Ans = INF ; for (re int i = 1 ; i <= L ; ++ i) { for (re int j = 1 ; j <= L; ++ j) { Ans = Min (Ans , F[N][i][j]) ; } } printf ("%d " , Ans) ; } fclose (stdin) , fclose (stdout) ; return 0 ; }