2742. Painting walls

5 阅读1分钟
class Solution {
    public int paintWalls(int[] cost, int[] time) {
        int n = cost.length;
        // Create a DP table where:
        // dp[i][remain] represents the minimum cost required to "unlock" painting for
        // 'remain' number of walls when considering walls from index i to n-1.
        int[][] dp = new int[n + 1][n + 1];
        
        // Base case initialization:
        // When we've processed all walls (i = n), if remain > 0 then it's impossible to cover
        // the required walls because there are no more walls to use for unlocking free painting.
        // Hence, we set dp[n][remain] to a large number (in this case, 1e9).
        // dp[n][0] is implicitly 0 since no further cost is needed if no walls remain.
        for (int i = 1; i <= n; i++) {
            dp[n][i] = (int) 1e9;
        }
        
        // Process walls in reverse order (from last wall to first).
        // This way, we build up the solution using the results of future decisions.
        for (int i = n - 1; i >= 0; i--) {
            // For each possible number of walls that still need to be "unlocked" for free painting.
            // 'remain' represents the number of walls that need to be painted (unlocked).
            for (int remain = 1; remain <= n; remain++) {
                // Option 1: Use the paid painter for wall i.
                // The cost incurred is cost[i].
                // The paid painter takes time[i] units of time to paint wall i.
                // During that time, the free painter can paint time[i] walls for free.
                // Since wall i is also painted by the paid painter, we reduce the remaining count by 1 + time[i].
                // We use Math.max to ensure the remaining count doesn't go below zero.
                int paint = cost[i] + dp[i + 1][Math.max(0, remain - 1 - time[i])];
                
                // Option 2: Skip using the paid painter for wall i.
                // In this case, no cost is incurred, but the number of walls that need to be covered remains the same.
                int dontPaint = dp[i + 1][remain];
                
                // The DP state dp[i][remain] is the minimum of the two options.
                dp[i][remain] = Math.min(paint, dontPaint);
            }
        }
        
        // The final answer is at dp[0][n], meaning starting from the first wall
        // with a requirement to cover all n walls.
        return dp[0][n];
    }
}