题目链接:leetcode.
提示竟然用回溯,那不也是一种暴力?
hhhhhhh我就说嘛,怎么可能这么简单,超时啦,16 / 60 个通过测试用例
我不会了,大概需要剪枝吧
*求最大值max_element(jobs.begin(), jobs.end())
class Solution {
int ans;
vector<int> tmp;
void dfs(const vector<int>& jobs, int k, int index)
{
if(index == jobs.size())
{
int maxx = 0;
for(auto num : tmp)
{
maxx = max(maxx, num);//最大工作时间
}
ans = min(ans, maxx);//最小的最大工作时间
return;
}
for(int i = 0;i < k;++i)
{
tmp[i] += jobs[index];
dfs(jobs, k, index + 1);
tmp[i] -= jobs[index];
}
}
public:
int minimumTimeRequired(vector<int>& jobs, int k) {
ans = INT_MAX;
tmp.resize(k, 0);
//人数和活一样多
if(k == jobs.size())
{
auto maxPos = max_element(jobs.begin(), jobs.end());
return *maxPos;
}
//人比活少
dfs(jobs, k, 0);
return ans;
}
};
参考题解多写了一句,结果还是超时 60 / 60 个通过测试用例
(先开始还不对呢,要先修改了tmp再判断跳不跳出,不然跳出来没修改回去,结果不对,而且这种情况最好排个序
class Solution {
int ans;
vector<int> tmp;
void dfs(const vector<int>& jobs, int k, int index)
{
if(index == jobs.size())
{
int maxx = 0;
for(auto num : tmp)
{
maxx = max(maxx, num);//最大工作时间
}
ans = min(ans, maxx);//最小的最大工作时间
return;
}
for(int i = 0;i < k;++i)
{
tmp[i] += jobs[index];
dfs(jobs, k, index + 1);
tmp[i] -= jobs[index];
////
if(tmp[i] == 0)
{
break;
}
}
}
public:
int minimumTimeRequired(vector<int>& jobs, int k) {
ans = INT_MAX;
tmp.resize(k, 0);
//人数和活一样多
if(k == jobs.size())
{
auto maxPos = max_element(jobs.begin(), jobs.end());
return *maxPos;
}
//人比活少
sort(jobs.begin(), jobs.end());
dfs(jobs, k, 0);
return ans;
}
};
官解的解决方式是,用二分查找
因为能满足最短时间为ans的组合,一定也能满足最短时间为limit (limit> ans)
查找那个最小的limit,左边界为数组最大值,右边界为数组和
对数组排序,先把工作时间长的给分配了
/*
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:7.2 MB, 在所有 C++ 提交中击败了70.05%的用户
*/
class Solution {
bool dfs(const vector<int>& jobs, vector<int>& tmp, int limit, int index)
{
if(index >= jobs.size())
{
return true;
}
//判断能不能所有工作时间都小于limit
for(int i = 0;i < tmp.size();++i)
{
if(tmp[i] + jobs[index] <= limit)
{
tmp[i] += jobs[index];
if(dfs(jobs, tmp, limit, index + 1))
return true;
tmp[i] -= jobs[index];
}
//后面的都不对 或 当前为 0 或 已经到达limit且后面都不对
//不必再试,剪枝
if(tmp[i] == 0 || tmp[i] + jobs[index] == limit)
{
break;
}
}
return false;
}
bool checkWork(const vector<int>& jobs, int k, int limit)
{
vector<int> tmp(k, 0);
return dfs(jobs, tmp, limit, 0);
}
public:
int minimumTimeRequired(vector<int>& jobs, int k) {
//人数和活一样多
if(k == jobs.size())
{
auto maxPos = max_element(jobs.begin(), jobs.end());
return *maxPos;
}
//人比活少
sort(jobs.begin(), jobs.end(), greater<int>());
int left = jobs[0], right = accumulate(jobs.begin(), jobs.end(), 0);
while(left < right)
{
int mid = left + (right - left) / 2;
if(checkWork(jobs, k, mid))
{
right = mid;
}
else
{
left = mid + 1;
}
}
return left;
}
};
题解还有一个动态规划的方法,emmmm先不看了吧
本文解析了一道关于分配工作的LeetCode题目,探讨了如何使用回溯算法找到最小的最大工作时间,并通过剪枝优化算法效率。最终采用了二分查找结合回溯的方法,实现了高效的解决方案。
955

被折叠的 条评论
为什么被折叠?



