前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LeetCode 1723. 完成所有工作的最短时间(DFS+剪枝 / 状态压缩DP)

LeetCode 1723. 完成所有工作的最短时间(DFS+剪枝 / 状态压缩DP)

作者头像
Michael阿明
发布2021-02-19 14:52:22
1K0
发布2021-02-19 14:52:22
举报
文章被收录于专栏:Michael阿明学习之路

文章目录

265 / 3871, 前6.85%

前3题题解:

1. 题目

给你一个整数数组 jobs ,其中 jobsi 是完成第 i 项工作要花费的时间。

请你将这些工作分配给 k 位工人。

所有工作都应该分配给工人,且每项工作只能分配给一位工人。

工人的 工作时间 是完成分配给他们的所有工作花费时间的总和

请你设计一套最佳的工作分配方案,使工人的 最大工作时间 得以 最小化 。

返回分配方案中尽可能 最小最大工作时间

代码语言:javascript
复制
示例 1:
输入:jobs = [3,2,3], k = 3
输出:3
解释:给每位工人分配一项工作,最大工作时间是 3 。

示例 2:
输入:jobs = [1,2,4,7,8], k = 2
输出:11
解释:按下述方式分配工作:
1 号工人:1、2、8(工作时间 = 1 + 2 + 8 = 11)
2 号工人:4、7(工作时间 = 4 + 7 = 11)
最大工作时间是 11 。
 
提示:
1 <= k <= jobs.length <= 12
1 <= jobs[i] <= 10^7

https://leetcode-cn.com/problems/find-minimum-time-to-finish-all-jobs/

2. 解题

2.1 DFS

  • 先排序,也可以不排序
  • 使用 DFS 暴力搜索,过程中进行剪枝
代码语言:javascript
复制
class Solution {
    int ans = INT_MAX;
public:
    int minimumTimeRequired(vector<int>& jobs, int k) {
        int n = jobs.size();
        // 不排序 88ms
        sort(jobs.begin(), jobs.end()); // 40ms
        // sort(jobs.rbegin(), jobs.rend()); // 680ms
        vector<int> time(k, 0);
        dfs(jobs, time, k, 0);
        return ans;
    }
    void dfs(vector<int>& jobs, vector<int>& time, int k, int idx)
    {
        if(idx == jobs.size())
        {
            int t = *max_element(time.begin(), time.end());
            if(t < ans)// 最大的时间总和 更小
                ans = t;
            return;
        }
        for(int i = 0; i < k; ++i)
        {
            if(time[i]+jobs[idx] > ans)
            //如果某人的时间超过答案,不可能是更优答案,剪枝
                continue;
            time[i] += jobs[idx];
            dfs(jobs, time, k, idx+1);
            time[i] -= jobs[idx];
            if(time[i] == 0)
                break;//搜完了,不加会超时
        }
    }
};

40 ms 7.6 MB C++

2.2 状态压缩DP

代码语言:javascript
复制
class Solution {
public:
    int minimumTimeRequired(vector<int>& jobs, int k) {
        int n = jobs.size();
        // 使用 12 位二进制数的 0,1 表示某个工作分配了没
        vector<int> time(1<<n, 0);
        for(int i = 1; i < (1<<n); ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if((i & (1<<j)) == 0)
                    continue;
                int left = i - (1<<j);//除去 j 工作外的工作
                time[i] = time[left]+jobs[j];
            }
        }
        vector<vector<int>> dp(k, vector<int>(1<<n, INT_MAX));
        // dp[k][sub] 表示 前 k 个人,处理 sub 任务子集 的最优分配时间
        for(int i = 0; i < (1<<n); ++i)
            dp[0][i] = time[i];
        for(int ki = 1; ki < k; ++ki)
        {
            for(int i = 0; i < (1<<n); ++i)
            {
                for(int s = i; s; s = i&(s-1))//枚举 i 的全部子集
                {
                    int left = i - s;
                    int t = max(dp[ki-1][left], time[s]);
                    dp[ki][i] = min(dp[ki][i], t);
                }
            }
        }
        return dp[k-1][(1<<n)-1];
    }
};

1352 ms 11.2 MB C++

附枚举子集 for(int s = i; s; s = (s-1) & i)

代码语言:javascript
复制
#include<bits/stdc++.h>
using namespace std;
int main()
{
	char buf[50];
    for(int i = 6; i <= 8; i++)
    {
    	cout << i << endl;
    	for(int s = i; s; s = (s-1)&i)
    	{
    		itoa(s, buf, 2);
    		printf(buf);
    		printf("\n");
    	}
    	cout << "--------" << endl;
    }
    return 0;
}
代码语言:javascript
复制
6
110
100
10
--------
7
111
110
101
100
11
10
1
--------
8
1000
--------
请按任意键继续. . .
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/01/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 1. 题目
  • 2. 解题
    • 2.1 DFS
      • 2.2 状态压缩DP
      相关产品与服务
      文件存储
      文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档