LeetCode 1235. 规划兼职工作

写了很长时间,写了很多遍。但是大致的思路一开始就有,在实现时出现了很多问题
基本的思路就是动态规划,但是我第一次写的时候,把dp建立在时间上,虽然这样理解起来比较简单,但是当出现某一工作时间跨度过长的情况时,就会造成很多的重复操作,造成超时

改进后的dp表基于工作数来建立,并对输入的数据按照工作结束的时间进行排序,这样dp[i]就表示有i个工作时的最大收益
则转移方程dp[i] = max(dp[i - 1], dp[k] + profit[i])

  • 其中dp[i - 1]表示不做第i个工作。
  • dp[k] + profit[i]表示做第i个工作,dp[k]是第i个工作开始前的时间内可以获得的最大收益,profit[i]为第 i个工作的收益

那么问题就剩下寻找这个k了,这里用的是循环遍历的方法(比较费时间),从当前工作i开始往前找,寻找第一个出现的工作k(由于根据结束时间对工作进行过排序),其中k的结束时间小于i的开始时间,就返回k。如果找不到就返回-1,代表如果做工作i则之前不会做任何的工作,之前的收益为0

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b)
    {
        return a[1] < b[1];
    }

	//寻找k
    int findK(const vector<vector<int>>& job, int p)
    {
        int start = job[p][0];
        for(int i = p - 1; i >= 0; i--)
        {
            if(job[i][1] <= start)
                return i;
        }
        return -1;
    }

    int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
        vector<vector<int>> job(startTime.size());
        for(int i = 0; i < startTime.size(); i++)
            job[i] = {startTime[i], endTime[i], profit[i]};
        sort(job.begin(), job.end(), cmp);
        vector<int> dp(startTime.size(), 0);
        dp[0] = job[0][2];
        for(int i = 1; i < dp.size(); i++)
        {
            int k = findK(job, i);
            if(k != -1)
                dp[i] = max(dp[i - 1], dp[k] + job[i][2]);
            else	//代表如果做i的话,之前的收益为0,之前没有做个任何的工作
                dp[i] = max(dp[i - 1], job[i][2]); 
        }
        return dp[dp.size() - 1];
    }
};

你可能感兴趣的:(题,leetcode,动态规划,算法)