20221022 - 1235. Maximum Profit in Job Scheduling 规划兼职工作(动态规划)

214 阅读1分钟

We have n jobs, where every job is scheduled to be done from startTime[i] to endTime[i], obtaining a profit of profit[i].

You're given the startTime, endTime and profit arrays, return the maximum profit you can take such that there are no two jobs in the subset with overlapping time range.

If you choose a job that ends at time X you will be able to start another job that starts at time X.

Example 1

Input: startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70]
Output: 120
Explanation: The subset chosen is the first and fourth job. 
Time range [1-3]+[3-6] , we get profit of 120 = 50 + 70.

Example 2

Input: startTime = [1,2,3,4,6], endTime = [3,5,10,6,9], profit = [20,20,100,70,60]
Output: 150
Explanation: The subset chosen is the first, fourth and fifth job. 
Profit obtained 150 = 20 + 70 + 60.

Example 3

Input: startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]
Output: 6

Constraints

  • 1 <= startTime.length == endTime.length == profit.length <= 5e4
  • 1 <= startTime[i] < endTime[i] <= 1e9
  • 1 <= profit[i] <= 1e4

Solution

题解:

我们首先将兼职工作按结束时间 endTime\textit{endTime} 从小到大进行排序。使用 dp[i]\textit{dp}[i] 表示前 ii 份兼职工作可以获得的最大报酬,初始时 dp[0]=0\textit{dp}[0] = 0,那么对于 i>0i \gt 0,我们有以下转移方程:

dp[i]=max(dp[i1],dp[k]+profit[i1])\textit{dp}[i] = \max(\textit{dp}[i - 1], \textit{dp}[k] + \textit{profit}[i - 1])

其中 kk 表示满足结束时间小于等于第 i1i - 1 份工作开始时间的兼职工作数量,可以通过二分查找获得。

int cmp(const void *pa, const void *pb)
{
    int *a = (int*)pa;
    int *b = (int*)pb;
    return a[1] - b[1];
}

int themax(int a, int b)
{
    return a > b ? a : b;
}

int jobScheduling(int* startTime, int startTimeSize, int* endTime, int endTimeSize, int* profit, int profitSize){
    int n = startTimeSize; 
    int job[n][3];
    for (int i = 0; i < n; i++) {
        job[i][0] = startTime[i];
        job[i][1] = endTime[i];
        job[i][2] = profit[i];
    }
    qsort(job, n, sizeof(job[0]), cmp);
    int dp[n + 1];
    for (int i = 0; i < n + 1; i++) dp[i] = 0;
    int left, right, mid;
    for (int i = 1; i < n + 1; i++) {
        left = 0;
        right = i - 1;
        while (left < right) {
            mid = left + (right - left) / 2;
            if (job[mid][1] > job[i - 1][0]) right = mid;
            else left = mid + 1;
        }
        dp[i] = themax(dp[i - 1], dp[left] + job[i - 1][2]);
    }
    return dp[n];
}
  • 按结束时间排序
  • 开始动态规划
  • 二分查找上一个元素

题目链接:1235. 规划兼职工作 - 力扣(LeetCode)