Minimum Difficulty of a Job Schedule

hard dp partition

Problem

You must finish a list of jobs in the given order over exactly d days, doing at least one job every day. A day's difficulty is the maximum difficulty among the jobs done that day, and the schedule's total difficulty is the sum of the daily difficulties. Return the minimum possible total, or -1 if there are fewer jobs than days (constraints: up to 300 jobs with difficulties 0..1000, and 1 ≤ d ≤ 10).

InputjobDifficulty = [6,5,4,3,2,1], d = 2
Output7
Do the first five jobs on day 1 (max 6) and the last job on day 2 (max 1): 6 + 1 = 7.

def min_difficulty(job_difficulty, d):
    n = len(job_difficulty)
    if n < d:
        return -1
    INF = float("inf")
    dp = [[INF] * (n + 1) for _ in range(d + 1)]
    dp[0][0] = 0
    for k in range(1, d + 1):
        for i in range(k, n + 1):
            mx = 0
            for j in range(i - 1, k - 2, -1):
                mx = max(mx, job_difficulty[j])
                cand = dp[k - 1][j] + mx
                if cand < dp[k][i]:
                    dp[k][i] = cand
    return dp[d][n]
function minDifficulty(jobDifficulty, d) {
  const n = jobDifficulty.length;
  if (n < d) return -1;
  const INF = Infinity;
  const dp = Array.from({ length: d + 1 }, () => new Array(n + 1).fill(INF));
  dp[0][0] = 0;
  for (let k = 1; k <= d; k++) {
    for (let i = k; i <= n; i++) {
      let mx = 0;
      for (let j = i - 1; j >= k - 1; j--) {
        mx = Math.max(mx, jobDifficulty[j]);
        dp[k][i] = Math.min(dp[k][i], dp[k - 1][j] + mx);
      }
    }
  }
  return dp[d][n];
}
int minDifficulty(int[] jobDifficulty, int d) {
    int n = jobDifficulty.length;
    if (n < d) return -1;
    int INF = 1_000_000_000;
    int[][] dp = new int[d + 1][n + 1];
    for (int[] row : dp) Arrays.fill(row, INF);
    dp[0][0] = 0;
    for (int k = 1; k <= d; k++) {
        for (int i = k; i <= n; i++) {
            int mx = 0;
            for (int j = i - 1; j >= k - 1; j--) {
                mx = Math.max(mx, jobDifficulty[j]);
                dp[k][i] = Math.min(dp[k][i], dp[k - 1][j] + mx);
            }
        }
    }
    return dp[d][n];
}
int minDifficulty(vector<int>& jobDifficulty, int d) {
    int n = jobDifficulty.size();
    if (n < d) return -1;
    const int INF = 1000000000;
    vector<vector<int>> dp(d + 1, vector<int>(n + 1, INF));
    dp[0][0] = 0;
    for (int k = 1; k <= d; k++) {
        for (int i = k; i <= n; i++) {
            int mx = 0;
            for (int j = i - 1; j >= k - 1; j--) {
                mx = max(mx, jobDifficulty[j]);
                dp[k][i] = min(dp[k][i], dp[k - 1][j] + mx);
            }
        }
    }
    return dp[d][n];
}
Time: O(d · n²) Space: O(d · n)