【LeetCode 1723】Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务

120 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务活动详情

一、题目描述

给定n个工人,和m个任务,每个任务有完成所需的时间,工人都是一样的。求一个分配方案,最小化最大的工人耗时,输出这个方案。

数据范围

n <= 12

二、思路分析

首先,我们立即就想到了二分答案,这很容易能看出是正确的。

但更大的问题是——如何进行 check ?

朴素想法: 贪心,依次对每个工人进行分配,从大的任务先开始,不能分了换下一个工人。这似乎很有效,但是实践结果是被最后几个数据卡了,贪心并不是最优解。

那怎么办呢?

不朴素想法: 因为人数很少,所以我们可以考虑使用暴搜,依次尝试把任务分配给每个工人,外加一些细节上的剪枝,比如说当某个工人无法分配任何任务的时候,那它之后的那些工人也就不需要再尝试了。

三、AC代码

class Solution {
public:
    int n;
    int load[1000];
    int a[10000];

    bool check(int mid, int k, int now) {
        if (now == n) return true;
        for (int i=0; i<k; i++) {
            if (load[i] + a[now] <= mid) {
                load[i] += a[now];
                if (check(mid, k, now + 1)) return true;
                load[i] -= a[now];
            }
            if (load[i] == 0) return false;
        }
        return false;
    }

    int minimumTimeRequired(vector<int>& jobs, int k) {
        n = jobs.size();
        for (int i=0; i<n; i++) a[i] = jobs[i];


        sort(a + 0, a + 0 + n);
        for (int i=0; i<n/2; i++) swap(a[i],a[n-i-1]);
        int l=0, r = 120000000;
        int ans = 999999999, mid;
        while (l <= r) {
            for (int i=0; i<20; i++) load[i]=0;
            mid = (l + r) / 2;
            if (check(mid, k, 0)) {
                ans = mid;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        return ans;
    }
};

四、总结

一开始考虑不够充分,贪心失败了,以后应当所思考一下贪心的正确性,避免浪费时间。