题目描述
一个公司有三个移动服务员,最初分别在位置1,2,3处。
如果某个位置(用一个整数表示)有一个请求,那么公司必须指派某名员工赶到那个地方去。
某一时刻只有一个员工能移动,且不允许在同样的位置出现两个员工。
从 p 到 q 移动一个员工,需要花费 c(p,q)。
这个函数不一定对称,但保证 c(p,p)=0。
给出N个请求,请求发生的位置分别为 p1~pN。
公司必须按顺序依次满足所有请求,且过程中不能去其他额外的位置,目标是最小化公司花费,请你帮忙计算这个最小花费。
输入格式
第1行有两个整数L,N,其中L是位置数量,N是请求数量,每个位置从1到L编号。
第2至L+1行每行包含L个非负整数,第i+1行的第j个数表示c(i,j) ,并且它小于2000。
最后一行包含N个整数,是请求列表。
一开始三个服务员分别在位置1,2,3。
输出格式
输出一个整数M,表示最小花费。
数据范围
3≤L≤200,
1≤N≤1000
输入样例
5 9
0 1 1 1 1
1 0 2 3 2
1 1 0 4 1
2 1 5 0 1
4 2 3 4 0
4 2 4 1 5 4 3 2 1
输出样例
5
算法
采用动态规划。本来想的是[i][][][],但是题目条件限制必须要在当前的位置,所以可以省去一维。
更新的时候只能采用刷表的办法,不能递归。初始化的时候自己做得比较麻烦。可以随便加一个去0的状态。
java 代码
import java.util.Scanner;
import java.util.Arrays;
class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int L = in.nextInt();
int N = in.nextInt();
int[][] graph = new int[L][L];
int[] queries = new int[N];
for (int i = 0; i < L; ++i) {
for (int j = 0; j < L; ++j) {
graph[i][j] = in.nextInt();
}
}
for (int i = 0; i < N; ++i) {
queries[i] = in.nextInt() - 1;
}
in.close();
System.out.println(minCost(graph, queries));
}
private static int minCost(int[][] graph, int[] queries) {
int n = queries.length, m = graph.length;
int INF = (int) 1e9;
int[][][] dp = new int[n][m][m];
for (int[][] d2 : dp) {
for (int[] d : d2) {
Arrays.fill(d, INF);
}
}
for (int i = 0; i < 3; ++i) {
for (int j = i + 1; j < 3; ++j) {
if (i == queries[0] || j == queries[0]) continue;
dp[0][i][j] = dp[0][j][i] = graph[3 - i - j][queries[0]];
}
}
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < m; ++j) {
for (int k = j + 1; k < m; ++k) {
int last = queries[i], cur = queries[i + 1];
if (j == last || k == last) continue;
dp[i + 1][k][j] = dp[i + 1][j][k] = Math.min(dp[i][j][k] + graph[last][cur], dp[i + 1][j][k]);
dp[i + 1][last][k] = dp[i + 1][k][last] = Math.min(dp[i][j][k] + graph[j][cur], dp[i + 1][k][last]);
dp[i + 1][last][j] = dp[i + 1][j][last] = Math.min(dp[i][j][k] + graph[k][cur], dp[i + 1][j][last]);
}
}
}
int ans = INF;
for (int j = 0; j < m; ++j) {
for (int k = j + 1; k < m; ++k) {
ans = Math.min(ans, dp[n - 1][j][k]);
}
}
return ans;
}
}