func minCostII(costs [][]int) int {
n := len(costs)
m := len(costs[0])
f := make([][]int, n + 1)
ans := 1000000
for i := 0; i <= n; i ++ {
f[i] = make([]int, m)
}
for i := 1; i <= n; i ++ {
for color := 0; color < m; color ++ {
f[i][color] = 114514
for k := 0; k < m; k ++ {
if k != color {
f[i][color] = min(f[i][color], f[i - 1][k] + costs[i - 1][color])
}
}
}
}
for i := 0; i < m; i ++ {
ans = min(ans, f[n][i])
}
return ans
}
当然,这里可以使用滚动数组来优化,但是我们的重点放在第二种解法上面
我们的解法 2 需要实现时间复杂度 O(nk) 的算法,我们可以在处理第二层循环的时候将这个嵌套循环分为两部分,第一部分一层 for 循环找到前面房子开销的最小值和第二小值,这里是因为我们在计算当前状态的时候,如果发现最小值的颜色和当前要涂的颜色相同,就只能去用第二小的值。于是,我们就可以写出来了:
func minCostII(costs [][]int) int {
n := len(costs)
m := len(costs[0])
f := make([][]int, n + 1)
ans := 1000000
for i := 0; i <= n; i ++ {
f[i] = make([]int, m)
}
for i := 1; i <= n; i ++ {
minCost1 := -1
minColor1 := -1
minCost2 := -1
minColor2 := -1
for color := 0; color < m; color++ {
currentCost := f[i-1][color]
if minColor1 == -1 || currentCost < minCost1 {
minCost2 = minCost1
minColor2 = minColor1
minCost1 = currentCost
minColor1 = color
} else if minColor2 == -1 || currentCost < minCost2 {
minCost2 = currentCost
minColor2 = color
}
}
for color := 0; color < m; color++ {
if color == minColor1 {
f[i][color] = f[i - 1][minColor2] + costs[i - 1][color]
} else {
f[i][color] = f[i - 1][minColor1] + costs[i - 1][color]
}
}
}
for i := 0; i < m; i ++ {
ans = min(ans, f[n][i])
}
return ans
}