1. 程式人生 > 其它 >Leetcode之完成所有工作最短的時間

Leetcode之完成所有工作最短的時間

技術標籤:leetcode和機試題leetcode

題目:

給你一個整數陣列 jobs ,其中 jobs[i] 是完成第 i 項工作要花費的時間。

請你將這些工作分配給 k 位工人。所有工作都應該分配給工人,且每項工作只能分配給一位工人。工人的 工作時間 是完成分配給他們的所有工作花費時間的總和。請你設計一套最佳的工作分配方案,使工人的 最大工作時間 得以 最小化 。

返回分配方案中儘可能 最小 的 最大工作時間 。

示例 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 。

程式碼:

方法一——狀態壓縮動態規劃:

class Solution {
public:
    int minimumTimeRequired(vector<int>& jobs, int k) {
        int n = jobs.size();
        vector<int> tot(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));
                tot[i] = tot[left] + jobs[j];
                break;
            }
        }
        
        vector<vector<int>> dp(k, vector<int>(1 << n, -1));
        for (int i = 0; i < (1 << n); i++) {
            dp[0][i] = tot[i];
        }
        
        for (int j = 1; j < k; j++) {
            for (int i = 0; i < (1 << n); i++) {
                int minv = INT_MAX;
                for (int s = i; s; s = (s - 1) & i) { // 列舉 i 的全部子集
                    int left = i - s;
                    int val = max(dp[j-1][left], tot[s]);
                    minv = min(minv, val);
                }
                dp[j][i] = minv;
            }
        }
        return dp[k-1][(1<<n)-1];
    }
};

思路:

設jobs 的長度為 NN,則可以用一個 [0,2^N]之間的整數代表 jobs 的任意一個子集。下文中,我們不加區分地用 i 表示「整數 i」或者「整數 i 對應的子集」

於是,令 tot[i] 代表子集 i的工作總時間。設子集 i的其中(任意)一個元素為 j,則 i-(1<<j) 代表了「子集 i中去掉了元素 j 後剩下的那部分」。因此,我們有
tot[i]=tot[i−(1<<j)]+jobs[j]。

隨後,我們設 dp[j][i] 表示:前 j個工人為了完成作業子集 i,需要花費的最大工作時間的最小值。

由於前 j個工人完成了作業子集 i,因此第 j個工人必然完成 i的某個子集 s,而其餘的工人完成子集 i-s。對於特定的 s 而言,前 j−1 個工人完成子集 i−s 需要花費的最大工作時間的最小值為 dp[j-1][i-s],而工人 jj 的工作時間為 tot[s],故此時總的最大工作時間的最小值為 max{dp[j−1][i−s],tot[s]}。

因此,根據題意,我們遍歷所有的子集 s ,並求出全域性的最小值,即
dp[j][i]=s⊆imin(max{dp[j−1][i−s],tot[s]})

最終,dp[k-1][(1<<N)-1]即為我們所求的答案。

方法二——: