Question

link

Given a set of n jobs with [start time, end time, cost], find a subset so that no 2 jobs overlap and the cost is maximum.

Let’s assume the input is already sorted by start_time.

Solution

Somebody mentioned Interval Graph, so check it out if you interested!

I am going to discuss both DP and recursive solution.

This question reminds me of [Question] 0-1 Knapsack Problem and [Question] Coin Change Problem, cuz the basic idea is to compare 2 conditions:

  1. include current element
  2. or, not include current element

A very good DP solution is presented in here. The code below is written by me and it’s very intuitive to read.

Leave me a comment if you have questions. And one more thing~ Happy new year!

Code

Dp

private int dpSolution(Job[] jobs, int size) {
    int[] dp = new int[size];
    dp[size - 1] = jobs[size - 1].cost;
    // cost of last job equals to just itself
    for (int k = size - 2; k >= 0; k--) {
        int next = findNextJob(jobs, k);
        int includeK = jobs[k].cost;
        if (next < size) {
            includeK += dp[next];
        }
        int excludeK = dp[k + 1];
        dp[k] = Math.max(includeK, excludeK);
    }
    return dp[0];
}

private int findNextJob(Job[] jobs, int k) {
    int finishTime = jobs[k].finish;
    int next = k + 1;
    while (next < jobs.length) {
        if (jobs[next].start < finishTime) {
            next++;
        } else {
            break;
        }
    }
    return next;
}

Recursion

public int recursiveSolution(Job[] jobs, int size, int k) {
    // max cost from (k)th job and onwards
    if (k == size) {
        return 0;
    }
    // (k)th job must not conflict with any previous job
    int next = findNextJob(jobs, k);
    int includeK = jobs[k].cost + recursiveSolution(jobs, size, next);
    int excludeK = recursiveSolution(jobs, size, k + 1);
    return Math.max(includeK, excludeK);
}

private int findNextJob(Job[] jobs, int k) {
    int finishTime = jobs[k].finish;
    int next = k + 1;
    while (next < jobs.length) {
        if (jobs[next].start < finishTime) {
            next++;
        } else {
            break;
        }
    }
    return next;
}