🌈【LeetCode 826. 安排工作以达到最大收益 】- JavaScript(动态规划)

112 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


【LeetCode 826. 安排工作以达到最大收益 】- JavaScript(动态规划)

题目描述

你有 n 个工作和 m 个工人。给定三个数组: difficulty, profit 和 worker ,其中:

  • difficulty[i] 表示第 i 个工作的难度,profit[i] 表示第 i 个工作的收益。

  • worker[i] 是第 i 个工人的能力,即该工人只能完成难度小于等于 worker[i] 的工作。

每个工人 最多 只能安排 一个 工作,但是一个工作可以 完成多次 。

  • 举个例子,如果 3 个工人都尝试完成一份报酬为 1的同样工作,那么总收益为1 的同样工作,那么总收益为 3 。如果一个工人不能完成任何工作,他的收益为 $0 。

返回 在把工人分配到工作岗位后,我们所能获得的最大利润 。

示例 1:

输入: difficulty = [2,4,6,8,10], profit = [10,20,30,40,50], worker = [4,5,6,7]

输出: 100

解释: 工人被分配的工作难度是 [4,4,6,6] ,分别获得 [20,20,30,30] 的收益。

动态规划

思路分析:

动态规划的思路:定义dp[i]:能力为i的工人能创造的最大收益。初值:dp[0]=0、dp[difficulty[i]]=profit[i]。存在一个问题,那就是一个difficulty[i]可能对应多个profit[i],所以上式可以改写为dp[difficulty[i]]=max(dp[difficulty[i]],profit[i])。

推导出状态转移方程:考虑到dp[i]随i单调递增的情况,方程如下dp[i]=max(dp[0],dp[1],...,dp[i])

实现时主要有下面三点规则需要注意:

  • 设工人为价值为0的工作
  • 求出包括工人在内的所有工作可以达到的最大价值
  • 按照价值重新排序,工人一定位于数组最前方

注意一个问题,就是当将difficult和profit进行捆绑之后,我们只需要依据profit进行从大到小排序就好了,然后对worker进行从大到小排序。一旦worker[i] > diff[i],继续对比就好了,不要重新将i=0. 这样没有意义。

var maxProfitAssignment = function(difficulty, profit, worker) {
  const l = difficulty.length;
  const map = new Map();

  for (let i = 0; i < l; i++) {
    map.set(difficulty[i], Math.max(map.get(difficulty[i]) || 0, profit[i]));
  }
  const max = Math.max(...difficulty, ...worker);
  const dp = new Array(max + 1).fill(0);
  for (let i = 1; i <= max; i++) {
    dp[i] = Math.max(dp[i - 1], map.get(i) || 0);
  }
  return worker.reduce((sum, item) => sum + dp[item], 0);
};

思考

最后说一句:资本主义真好啊,难度高收益还少👀🤞


感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤