持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【LeetCode 826. 安排工作以达到最大收益 】- JavaScript(动态规划)
题目描述
你有 n 个工作和 m 个工人。给定三个数组: difficulty, profit 和 worker ,其中:
difficulty[i] 表示第 i 个工作的难度,profit[i] 表示第 i 个工作的收益。
worker[i] 是第 i 个工人的能力,即该工人只能完成难度小于等于 worker[i] 的工作。
每个工人 最多 只能安排 一个 工作,但是一个工作可以 完成多次 。
- 举个例子,如果 3 个工人都尝试完成一份报酬为 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);
};
思考
最后说一句:资本主义真好啊,难度高收益还少👀🤞
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤