粉刷房子 III
难度:
标签:
题目描述
代码结果
运行时间: 72 ms, 内存: 19.1 MB
/*
* This solution uses Java Streams to solve the problem of painting houses to form a specific number of blocks with minimum cost.
* We leverage the same dynamic programming approach but implement it in a more functional style with Streams.
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public int minCost(int[] houses, int[][] cost, int m, int n, int target) {
int MAX_COST = 1000001;
int[][][] dp = new int[m][target + 1][n + 1];
for (int i = 0; i < m; i++) {
for (int j = 0; j <= target; j++) {
Arrays.fill(dp[i][j], MAX_COST);
}
}
IntStream.range(1, n + 1).forEach(k -> {
if (houses[0] == 0) {
dp[0][1][k] = cost[0][k - 1];
} else if (houses[0] == k) {
dp[0][1][k] = 0;
}
});
IntStream.range(1, m).forEach(i -> {
IntStream.range(1, target + 1).forEach(j -> {
IntStream.range(1, n + 1).forEach(k -> {
if (houses[i] != 0 && houses[i] != k) {
return;
}
int currentCost = houses[i] == 0 ? cost[i][k - 1] : 0;
IntStream.range(1, n + 1).forEach(kPrev -> {
if (k == kPrev) {
dp[i][j][k] = Math.min(dp[i][j][k], dp[i - 1][j][kPrev] + currentCost);
} else {
dp[i][j][k] = Math.min(dp[i][j][k], dp[i - 1][j - 1][kPrev] + currentCost);
}
});
});
});
});
return IntStream.range(1, n + 1)
.map(k -> dp[m - 1][target][k])
.min()
.orElse(MAX_COST) == MAX_COST ? -1 : IntStream.range(1, n + 1).map(k -> dp[m - 1][target][k]).min().orElse(MAX_COST);
}
}
解释
方法:
这个题解使用了动态规划的方法。状态定义为 dp[i][t][j],表示前 i+1 个房子构成 t+1 个街区,且第 i 个房子颜色为 j+1 时的最小花费。初始状态处理第一个房子的颜色和花费。对于每个房子,如果未涂色,考虑涂不同颜色的花费;如果已涂色,则直接更新花费。计算时,保持两个最小值(min_idx 和 min_idx_),用于优化时间复杂度,避免重复计算。最后返回所有情况中的最小花费,如果不存在有效方案则返回 -1。
时间复杂度:
O(m * target * n * n)
空间复杂度:
O(m * target * n)
代码细节讲解
🦆
为什么在处理第一个房子的初始化状态时,只有当houses[0]为0时才从cost数组中取值,已涂色的房子花费为0而不是其实际花费?
▷🦆
动态规划中的状态转移方程是如何确保只形成target个街区的,能详细解释下其中的逻辑吗?
▷🦆
在代码中,min_t和max_t的计算公式是如何得出的,这两个值分别代表什么含义?
▷🦆
你是如何处理涂色成本计算中的两个最小值(min_idx 和 min_idx_)的?这种处理方法有什么特别的考量吗?
▷