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

本文探讨了一种使用二分查找、回溯和剪枝策略来解决工作量分配问题的方法。通过优先分配大工作量,结合二分查找确定最短时间范围,然后递归分配任务并进行剪枝,最终找到满足条件的最短时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:这种题我思考了三分钟想不出好的办法,直接看官方解答,并试图看懂了一种解题,即二分查找+回溯+剪枝
先考虑工作量顺序的分配,正如解答所说要先分配工作量大的工作,因为越到后面工作量越大越难分配(但其实从小到大分配也是一样能够解题的)
接下来考虑二分查找,这一题的思路其实是自己选择出答案再进行判断,利用二分查找能够更快的得到最短时间,这里需要考虑二分查找的上下限,如果只有一个工人,则所有工作都由他一人完成,所以此题的右边界是工作量之和;如果工作数和工人一样多,那么最短的时间就是工作量最大的那一个,这就是左边界。
回溯:就是对每一份工作,对每一个工人进行判断,如果在我们设定的最大量内,就可以考虑下一个工作,若超出界限,就要循环到下一个工人,如果全部不满足说明此限制不合理。关于剪枝,官方解答的一种剪枝没有理解,我只理解了对于第i个工人来说如果没有分配到工作,那么就不能对i+1个工人分配工作,说明当前设定的最短时间不合理,因此直接break循环返回false
对于满足返回true的情况来说,说明需要的最短时间将不大于当前设定的时间,所以右边界变为mid(即(left+right)/2),如果返回的false,说明需要的最短时间一定大于当前设定的时间,因此左边界left就要等于mid+1.

class Solution {
    bool Judy(vector<int>& jobs,vector<int>& worker,int sit,int limit)
    {
        //当工作都分配完了,就说明此方案可行
        if(sit>=jobs.size()) return true;
        //轮流遍历工人获取工作量
        for(int i=0;i<worker.size();++i)
        {
            //先加上当前工作的工作量
            worker[i]+=jobs[sit];
            //如果不大于限制
            if(worker[i]<=limit)
               //需要讨论下一个工作分配情况
               if(Judy(jobs,worker,sit+1,limit))
                 return true;
            //不满足的话就需要减去加上的工作量,回溯
            worker[i]-=jobs[sit];
            //这里剪枝
            //如果i工人没有分配到工作,那么i+1工人一定也不能分配工作
            if(worker[i]==0) break;
        }
        return false;
    }
    bool JudyMid(vector<int>& jobs,int& limit,int& k)
    {
        //worker[i]为第i+1个工人需要完成的工作量
        vector<int> worker(k);
        return Judy(jobs,worker,0,limit);
    }
public:
    int minimumTimeRequired(vector<int>& jobs, int k) {
        //先要排序,至于从小到大还是从大到小都能够求出答案
        //从大到小排序求解会提高解题效率
        sort(jobs.begin(),jobs.end(),greater<int>());
        //左边界为工作量最大的那一个
        int left=jobs[0];
        //右边界为工作量总和
        int right=accumulate(jobs.begin(),jobs.end(),0);
        //二分查找
        while(left<right)
        {
            //mid为设定的最小时间
            int mid=(left+right)/2;
            //当前时间符合说明最终解不大于mid,改变右边界
            if(JudyMid(jobs,mid,k))  right=mid;
            //否则最终解大于mid改变左边界
            else left=mid+1;
        }
        return right;
    }
};
深度优先搜索(DFS)算法是一种用于遍历或搜索树或图的算法。它可以用于解决许多问题,包括求铁路完成短时间。DFS算法的基本思想是尽可能深地搜索图的分支,当节点v的所有尚未被探索的边都已被探寻过,搜索将回溯到发现节点v的那条边的起始节点。 以下是一个使用DFS算法求铁路完成短时间的示例: 假设我们有一个铁路网络图,其中节点表示车站,边表示铁路线路,每条边有一个权重表示通过该线路所需的时间。我们需要找到从起点到终点的短时间。 ```python def dfs(graph, start, end, visited, path, shortest_time): visited[start] = True path.append(start) if start == end: current_time = sum(graph[path[i]][path[i+1]] for i in range(len(path)-1)) if current_time < shortest_time[0]: shortest_time[0] = current_time else: for neighbor, weight in graph[start].items(): if not visited[neighbor]: dfs(graph, neighbor, end, visited, path, shortest_time) path.pop() visited[start] = False # 示例铁路网络图 graph = { 'A': {'B': 5, 'C': 2}, 'B': {'C': 1, 'D': 3}, 'C': {'B': 3, 'D': 7}, 'D': {'E': 2}, 'E': {} } start_node = 'A' end_node = 'E' shortest_time = [float('inf')] visited = {node: False for node in graph} path = [] dfs(graph, start_node, end_node, visited, path, shortest_time) print(f"短时间: {shortest_time[0]}") ``` 在这个示例中,我们定义了一个铁路网络图 `graph`,其中每个节点表示一个车站,每个边表示一条铁路线路,权重表示通过该线路所需的时间。我们使用DFS算法从起点 `'A'` 开始,遍历整个图,直到找到终点 `'E'`,并记录短时间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值