(nice!!!)LeetCode 1235.规划兼职工作(动态规划+二分查找)

1235.规划兼职工作

在这里插入图片描述
在这里插入图片描述
思路:动态规划+二分查找。dp[i]表示在前i份工作里可选的最大薪水。我们先按工作结束时间升序排列,然后在for循环遍历到第i份工作时,考虑选它或者不选它。不选第i份工作,即dp[i]=dp[i-1];选第i份工作,需要找到结束时间都小于"第i份工作开始的时间"的工作数量。由于我们的遍历是按照工作结束时间升序进行遍历的。那么我们找到最后一个<="第i份工作开始的时间"的下标l,然后dp[i]=dp[l]+nd[i].p。最后选最大的状态转移方程dp[i]=max(dp[i-1],dp[l]+nd[i].p)即可。

class Solution {
public:
    typedef struct Node{
        int s,e,p;
        bool friend operator<(struct Node a,struct Node b){
            return a.e<b.e;
        }
    }node;
    int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
        int n=startTime.size();
        node nd[50010];
        nd[0]={0,0,0};//处理二分边界
        for(int i=0;i<n;i++){
            nd[i+1]={startTime[i],endTime[i],profit[i]};
        }
        sort(nd,nd+n+1);
        int dp[50010];
        dp[0]=nd[0].p;
        for(int i=1;i<=n;i++){
            int l=0,r=i-1;
            while(l<r){
                int mid=(l+r+1)/2;
                if(nd[mid].e<=nd[i].s) l=mid;
                else r=mid-1;
            }
            dp[i]=max(dp[i-1],dp[l]+nd[i].p);
        }
        return dp[n];
    }
};

思考:在这里,如果dp[i]表示选第i份工作的最大薪水,那么我们就得遍历一遍“所有结束时间”小于“第i份工作开始时间”的工作,这样的话时间就会超时。所以在定义状态时,需要认真思考状态的含义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值