题目1723. 完成所有工作的最短时间:

题解:

递归回溯模板超时

按照模板+简单剪枝,超时

class Solution {
private:vector<int> sum;int mintime;int n;
public:void backtrack(int u, int nowmax, vector<int>& jobs, int k){//剪枝1if(nowmax >= mintime) return;if(u == n){mintime = nowmax;return;}for(int ki = 0; ki < k; ki++){//剪枝2if(sum[ki] >= mintime){continue;}sum[ki]+=jobs[i];backtrack(i+1,max(nowmax,sum[ki]),jobs,k);sum[ki]-=jobs[i];}}int minimumTimeRequired(vector<int>& jobs, int k) {n = jobs.size();mintime = INT_MAX;sum.resize(k,0);backtrack(0,0,jobs,k);return mintime;}
};

递归+优先分配「空闲工人」

class Solution {
/**
* u     : 当前处理到那个 job
* used  : 当前分配给了多少个工人了
* sum   : 工人的分配情况          例如:sum[0] = x 代表 0 号工人工作量为 x
* nowmax   : 当前的「最大工作时间」
*/
public:vector<int> jobs;vector<int> sum;int mintime;int n;int k;int minimumTimeRequired(vector<int>& _jobs, int _k) {jobs = _jobs;k=_k;n = jobs.size();mintime = INT_MAX;sum.resize(k,0);backtrack(0,0,0);return mintime;}void backtrack(int u, int used, int nowmax){//当最大工作量maxs 大于 ans 结束递归,剪枝if(nowmax >= mintime){return;}//当工作分配完毕if(u == n){mintime = nowmax;return;}//以下是 尽量平均分配工作 // 优先分配给「空闲工人」if (used < k)//当有空闲的打工人 {sum[used] = jobs[u];backtrack(u + 1, used + 1, max(sum[used], nowmax));sum[used] = 0;}//当尝试完平均分配工作,就该尝试侧重分配工作了,即不平均分配for(int ki = 0; ki < used; ki++){sum[ki]+=jobs[u];backtrack(u + 1, used, max(sum[ki], nowmax));sum[ki]-=jobs[u];}}};

二分查找 + 回溯 + 剪枝

class Solution {
public:bool backtrack(vector<int>& jobs, vector<int>& workloads, int idx, int limit) {if (idx >= jobs.size()) {return true;}int cur = jobs[idx];for (auto& workload : workloads) {if (workload + cur <= limit) {workload += cur;if (backtrack(jobs, workloads, idx + 1, limit)) {return true;}workload -= cur;}// 如果当前工人未被分配工作,那么下一个工人也必然未被分配工作// 或者当前工作恰能使该工人的工作量达到了上限// 这两种情况下我们无需尝试继续分配工作if (workload == 0 || workload + cur == limit) {break;}}return false;}bool check(vector<int>& jobs, int k, int limit) {vector<int> workloads(k, 0);return backtrack(jobs, workloads, 0, limit);}int minimumTimeRequired(vector<int>& jobs, int k) {sort(jobs.begin(), jobs.end(), greater<int>());int l = jobs[0], r = accumulate(jobs.begin(), jobs.end(), 0);while (l < r) {int mid = (l + r) >> 1;if (check(jobs, k, mid)) {r = mid;} else {l = mid + 1;}}return l;}
};

动态规划 + 状态压缩

class Solution {
public:int minimumTimeRequired(vector<int>& jobs, int k) {int n = jobs.size();// sum[i]: 分配情况为i时的工作时间总和vector<int> sum(1 << n);//每种分配方案耗时长度// 比如jobs:[1,2,4,7,8],工作情况为5(00101,1表示已分配)时,工作时间总和:1+4=5for (int i = 1; i < (1 << n); i++) {// __builtin_ctz返回后面的0的个数,和__builtin_clz相对。//x表示当前工作序号,y表示前面一个方案的序号int x = __builtin_ctz(i), y = i - (1 << x);//计算当前方案 = 前一个方案sum[i] = sum[y] + jobs[x];}/**或者这样算const int n = jobs.size();const int m = 1 << n;  // the maximal value of bitmaskvector<int> sums(m);  // the total working time of every subset of worksfor (int b = 0; b < m; ++b) {for (int i = 0; i < n; ++i) {if ((1 << i) & b) sums[b] += jobs[i];}}**///dp[i][j]: 给i个工人在分配情况j时的最大值的最小值vector<vector<int>> dp(k, vector<int>(1 << n));for (int i = 0; i < (1 << n); i++) {// 给前面1个人分配工作情况为i时的最大时间(即所有工人的工作时间的最大值)的最小值dp[0][i] = sum[i];}for (int i = 1; i < k; i++) {for (int j = 0; j < (1 << n); j++) {int minn = INT_MAX;// 针对分配情况j:第i个工人可以分配j的任何一个子集,循坏计算出最大值的最小值// 比如j=11,即二进制1011,即第0,1,3个工作需分配。此时第i个工人可以分配的情况如下:// 1011,1010,1001,1000,0011,0010,0001,即枚举j的子集分配给第i个工人// j的子集计算通过 (x - 1) & j,即在j表示的二进制范围内(&j)for (int x = j; x!=0; x = (x - 1) & j) {minn = min(minn, max(dp[i - 1][j - x], sum[x]));}dp[i][j] = minn;}}return dp[k - 1][(1 << n) - 1];}
};

状态压缩2


class Solution {
public:int minimumTimeRequired(vector<int>& jobs, int k) {int n = jobs.size();int maxN = 1 << n;// 计算每个排列组合所消耗的事件// vector<int> time(1<<n, 0);int* time = new int[maxN];memset(time, 0, sizeof(int)*maxN);for (int i = 1; i < maxN; ++i){// 遍历j的编号,其实就是bit位,需要正好i对应的bit也是1才计算for (int j = 0; j < n; ++j){if (i & (1<<j)){// 计算后就可以结束,到下一个itime[i] = time[i-(1<<j)] + jobs[j];break;}}// printf("%X %d\n", i, time[i]);}// 构建d// vector<vector<int>> d(k, vector<int>(maxN, 0));int** d = new int*[k];for (int i = 0; i < k; ++i){d[i] = new int[maxN];memset(d[i], 0, sizeof(int)*maxN);}// 初始化单个工人情况,这里j=0for (int i = 0; i < maxN; ++i){d[0][i] = time[i];}for (int j = 1; j < k; ++j){for (int i = 1; i < maxN; ++i){int minSum = INT_MAX;//  坑:s必须大于0否则会进入循环,因为s无法再减少for (int s = i; s > 0; s = (s-1)&i){minSum = min(minSum, max(time[s], d[j-1][i-s]));}d[j][i] = minSum;}}return d[k-1][maxN-1];}
};

其他:

•int __builtin_ffs (unsigned int x)
返回x的最后一位1的是从后向前第几位,比如7368(1110011001000)返回4。
•int __builtin_clz (unsigned int x)
返回前导的0的个数。
•int __builtin_ctz (unsigned int x)
返回后面的0个个数,和__builtin_clz相对。
•int __builtin_popcount (unsigned int x)
返回二进制表示中1的个数。
•int __builtin_parity (unsigned int x)
返回x的奇偶校验位,也就是x的1的个数模2的结果。

此外,这些函数都有相应的usigned long和usigned long long版本,只需要在函数名后面加上l或ll就可以了,比如int __builtin_clzll。

Leetcode-二分+递归/回溯-1723. 完成所有工作的最短时间相关推荐

  1. LeetCode每日一题: 1723. 完成所有工作的最短时间

    1723. 完成所有工作的最短时间 题目 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工作都应该分配给工人,且每项工作 ...

  2. 【LeetCode/力扣】1723. 完成所有工作的最短时间

    1 题目描述 题目链接:https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/ 给你一个整数数组 jobs ,其中 ...

  3. leetcode 1723.完成所有工作的最短时间 - 二分+递归

    leetcode 1723.完成所有工作的最短时间 - 二分+递归 题干 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有 ...

  4. [leetcode每日一题2021/5/8]1723. 完成所有工作的最短时间

    1723. 完成所有工作的最短时间 题目 思路 动态规划 状态转移方程 优化 求和打表 快速枚举每种选取情况jjj的子集ppp 代码 算法复杂度 题目来源于leetcode,解法和思路仅代表个人观点. ...

  5. 【LeetCode每日一题】1723. 完成所有工作的最短时间

    [LeetCode每日一题]1723. 完成所有工作的最短时间 [1] 1723. 完成所有工作的最短时间 [2] 473. 火柴拼正方形 [1] 1723. 完成所有工作的最短时间 题目: 给你一个 ...

  6. (leetcode)1723. 完成所有工作的最短时间 -2021/5/8

    文章目录 1723. 完成所有工作的最短时间 javascript 1723. 完成所有工作的最短时间 javascript 题目: 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i ...

  7. LeetCode 1723 完成所有工作的最短时间 题解

    LeetCode 1723 完成所有工作的最短时间 题解 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工作都应该分配给 ...

  8. 1723. 完成所有工作的最短时间

    原题链接:1723. 完成所有工作的最短时间 solution:         dfs + 回溯 + 剪枝 ①结束条件:任务分配完成,maxt保存所有工人的最大工作时长,再用maxt和以前的最大工作 ...

  9. leetcode 1723. 完成所有工作的最短时间(二分+剪枝+回溯)

    给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工作都应该分配给工人,且每项工作只能分配给一位工人.工人的 工作时间 是完 ...

最新文章

  1. 多篇开源CVPR 2020 语义分割论文
  2. 关于c++中的Debug以及runtime_error之segment_fault
  3. git从master转到开发分支
  4. struts启动过滤器异常_面试必备:网关异常了怎么办?如何做全局异常处理?
  5. 群人各说什么是哈希算法?
  6. 树莓派的几种登录方式及树莓派的网络配置
  7. [转]CSS浏览器兼容问题总结
  8. python︱matplotlib使用(读入、显示、写出、opencv混用、格式转换...)
  9. 玩家可以输入辅助指令_三菱FX系列PLC输入输出与辅助继电器之间有什么关系?...
  10. DVWA——SQL盲注(全等级)
  11. 如何安装vue并创建vue.js框架项目
  12. 苹果6s最大屏幕尺寸_苹果 iPhone 12 Pro DXOMARK 屏幕评分 87 分,最大问题是黄色色偏 - 苹果,iPhone...
  13. 字节跳动,野心十足,十年有可能打败腾讯成为第二个互联网巨头吗?
  14. OLAP分析引擎Druid配置文件详解(五):MiddleManager配置文件
  15. 问题(ArcGIS):去除栅格不需要的Value(背景值0)
  16. Axure 元件库-原型
  17. 关于印发《深圳市福田区稳企惠民纾困“十条”政策》的通知
  18. 在一台Ubuntu计算机上构建Hyperledger Fabric网络
  19. TL-X19固件汇总(1.01-5.07+兔斯基美化版)带详细更新说明
  20. 西雅图Oracle公寓租赁,西雅图Seattle租房攻略

热门文章

  1. 农村土地确权之调查公示 —— 地块分布图制作说明
  2. Java的泛型---(英雄联盟集合嵌套案例)
  3. 怎么旋转PDF文件中的页面
  4. conver Json to map by fastJson
  5. MATHLAB GUI编程简易入门
  6. 今日头条、抖音创始人张一鸣
  7. 关于微信小程序跳转到H5,然后从H5又跳回微信小程序问题的资料
  8. Android 使用Notification进行消息提示
  9. 智能优化算法:海鸥算法原理及Matlab代码
  10. RSE2022/云检测:A hybrid generative adversarial network for weakly-supervised cloud detection 多光谱图像弱监督云检