定义 f(i,j) 表示用第 i 个及其右侧的工厂,修理第 j 个及其右侧的机器人,机器人移动的最小总距离。
枚举第 i 个工厂修了 k 个机器人,则有 f(i,j) = \min\limits_{k}^{}{f(i+1,j+k) + \text{cost}(i,j,k)。
这里 cost}(i,j,k) 表示第 i 个工厂修复从 j 到 j+k-1 的机器人,移动距离就是这些机器人到第 i 个工厂的距离之和。
注意 k\le\textit{limit}[i]。
[sol1-Python3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defminimumTotalDistance(self, robot: List[int], factory: List[List[int]]) -> int: factory.sort(key=lambda f: f[0]) robot.sort() n, m = len(factory), len(robot) @cache deff(i: int, j: int) -> int: if j == m: return0 if i == n - 1: if m - j > factory[i][1]: return inf returnsum(abs(x - factory[i][0]) for x in robot[j:]) res = f(i + 1, j) s, k = 0, 1 while k <= factory[i][1] and j + k - 1 < m: s += abs(robot[j + k - 1] - factory[i][0]) res = min(res, s + f(i + 1, j + k)) k += 1 return res return f(0, 0)
funcminimumTotalDistance(robot []int, factory [][]int)int64 { sort.Slice(factory, func(i, j int)bool { return factory[i][0] < factory[j][0] }) sort.Ints(robot) n, m := len(factory), len(robot) dp := make([][]int, n) for i := range dp { dp[i] = make([]int, m) for j := range dp[i] { dp[i][j] = -1 } } var f func(int, int)int f = func(i, j int) (res int) { if j >= m { return } dv := &dp[i][j] if *dv != -1 { return *dv } deferfunc() { *dv = res }() if i == n-1 { if m-j > factory[i][1] { return1e18 } for _, x := range robot[j:] { res += abs(x - factory[i][0]) } return } res = f(i+1, j) for s, k := 0, 1; k <= factory[i][1] && j+k-1 < m; k++ { s += abs(robot[j+k-1] - factory[i][0]) res = min(res, s+f(i+1, j+k)) } return } returnint64(f(0, 0)) }
funcabs(x int)int { if x < 0 { return -x } return x } funcmin(a, b int)int { if a > b { return b } return a }