当前位置:   article > 正文

【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];

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 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];
        }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/182145
推荐阅读
相关标签
  

闽ICP备14008679号