Description
Solution
以三个员工的位置作为状态, 第次询问作为阶段
可以得出 雏形
表示完成第次询问, 且员工位置分别在时的最小花费
考虑其能够更新的状态 :
但是以此作为状态的时空复杂度为, 无论是空间和时间都无法承受 .
这时可以观察到, 当完成上一个询问时, 已经有一个员工位置确定下来了.
于是可以设表示完成第次询问, 且员工位置分别在时的最小花费
转移时同理 .
Attention
以从 到 位置为例
容易写成
正确的却是
错误的原因就在于没有考虑所要更新的状态会去更新哪些状态
由于省略了一维, 在将一个员工 H 转移到新位置的时,
H 对于询问来说, 相当于那个省略的一维,
那个在 询问中省略的 P员工, 对于询问来说, 却是没有省略的那个员工,
所以转移新位置时将 P员工 放在已知的那个位置
Code
#include<bits/stdc++.h>
#define reg register
int read(){
int s = 0, flag = 1;
char c;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
int N, M;
int co[205][205];
int dp[1005][205][205];
int Que[1005];
void Work(){
N = read(), M = read();
for(reg int i = 1; i <= N; i ++)
for(reg int j = 1; j <= N; j ++) co[i][j] = read();
for(reg int i = 1; i <= M; i ++) Que[i] = read();
memset(dp, 0x3f, sizeof dp);
Que[0] = 3, dp[0][1][2] = 0;
int Ans = 0x3f3f3f3f;
for(reg int i = 1; i <= M; i ++)
for(reg int x = 1; x <= N; x ++)
for(reg int y = 1; y <= N; y ++){
if(Que[i-1] == x || Que[i-1] == y || x == y) continue ;
if(Que[i] != y && Que[i] != Que[i-1]){
int temp = dp[i][Que[i-1]][y] = std::min(dp[i][Que[i-1]][y], dp[i-1][x][y] + co[x][Que[i]]);
if(i == M) Ans = std::min(Ans, temp);
}
if(Que[i] != x && Que[i] != Que[i-1]){
int temp = dp[i][x][Que[i-1]] = std::min(dp[i][x][Que[i-1]], dp[i-1][x][y] + co[y][Que[i]]);
if(i == M) Ans = std::min(Ans, temp);
}
if(Que[i] != x && Que[i] != y){
int temp = dp[i][x][y] = std::min(dp[i][x][y], dp[i-1][x][y] + co[Que[i-1]][Que[i]]);
if(i == M) Ans = std::min(Ans, temp);
}
}
printf("%d
", Ans);
}
int main(){
int T = read();
while(T --) Work();
return 0;
}