【LeetCode】会议调度问题 (动态规划)

【参考:会议室调度算法集锦_阿飞算法的博客-CSDN博客

1751. 最多可以参加的会议数目 II hard

【参考:1751. 最多可以参加的会议数目 II - 力扣(LeetCode)

【参考:【阿飞算法】畅游面试中的动态规划套路-最多可以参加的会议数目 II - 最多可以参加的会议数目 II - 力扣(LeetCode) 循序渐进

  • 自顶向下记忆化递归

memo[curr][k] : 表示处理到编号curr这个会议,还剩余k次参加会议机会所能获取的价值的最大值

class Solution {
    int[][] memo;
    public int maxValue(int[][] events, int k) {
        int n=events.length;
        // 因为递归是自顶向下,所以按照开始时间排序
        Arrays.sort(events,(int[] a,int[] b)-> {return a[0]-b[0];});
        memo=new int[n][k+1]; // 会议数量[0,n-1],能参加的最多会议数目[1,k]
        int res=helper(events,0,n,k); // 从第一个会议开始 注意下标为0
        return res;
    }
    // cur 当前的会议编号[0,n-1], n 会议数量, k 剩余参加次数 [1,k]
    int helper(int[][] events,int cur,int n,int k){
        // 出口 cur到达末尾 或者 剩余参加次数用完了
        if(cur==n || k==0) return 0;
        // 查表
        if(memo[cur][k]!=0) return memo[cur][k];
        // 从前往后找 找到第一个开始时间大于cur的结束时间的会议编号i (可以二分来加速)
        int i=0;
        for(i=cur+1;i<n;i++){
            if (events[i][0] > events[cur][1]) break;
        }
        // 参加编号为cur的会议,剩余参加次数-1,下个会议是i
        int join=helper(events,i,n,k-1) + events[cur][2]; // 加上这个会议的value
        // 不参加编号为cur的会议,下一个会议是cur+1
        int joinNo=helper(events,cur+1,n,k);

        int ans=Math.max(join,joinNo); // 取最大值

        memo[cur][k]=ans;// 填充表格

        return memo[cur][k];

    }
}
  • dp

待深化理解

class Solution {
      public int maxValue(int[][] events, int k) {
            int n = events.length;
            // 因为我们要找 p,我们需要先对 events 的结束时间排序,然后找从右往左找,找到第一个满足 结束时间 小于 当前事件的开始时间 的事件,就是 last
            Arrays.sort(events, (o1, o2) -> o1[1] - o2[1]);

            //`dp[i][j]`表示在前`i`个会议中,最多只能参加`j`个会议,所能获取到的最大价值
            int[][] dp = new int[n + 1][k + 1];

            for (int i = 1; i <= n; i++) {
                int[] curr = events[i - 1];
                int start = curr[0], end = curr[1], value = curr[2];
                // [i+1..n]会议已经遍历过了
                // 从右往左找 最靠近i的且其结束时间比i的开始时间小的那个会议,记为p
                int p=0;
                for (p=i-1;p>=1;p--){
                    if(events[p-1][1] < start) break;
                }
                //遍历前这 k次参加会议的机会
                for (int j = 1; j <= k; j++) {
                    dp[i][j] = Math.max(dp[i - 1][j], // 不参加当前i会议
                                        dp[p][j - 1] + value); // 参加当前i 会议
                }
            }
            return dp[n][k];
        }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值