美文网首页
1723. 完成所有工作的最短时间

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

作者: 来到了没有知识的荒原 | 来源:发表于2021-09-01 15:42 被阅读0次

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

1. 状压+二分

这个写法跟这道题类似 1986. 完成任务的最少工作时间段

class Solution {
 public:
  int minimumTimeRequired(vector<int>& jobs, int k) {
    int n = jobs.size();
    vector<int> tot(1 << n);
    for (int i = 0; i < (1 << n); i++) {
      for (int j = 0; j < n; j++) {
        if (i & (1 << j)) {
          tot[i] = tot[i - (1 << j)] + jobs[j];
          break;
        }
      }
    }

    int l = 0, r = 0;
    for (auto i : jobs) {
      r += i;
      l = max(l, i);
    }

    while (l < r) {
      int x = (l + r) >> 1;
      // dp[i] : 处理集合为 i 的工作,需要最少员工的数量
      int dp[1 << n];
      memset(dp, 0x3f, sizeof dp);
      dp[0] = 0;  // 处理集合为0需要0个员工
      for (int i = 0; i < (1 << n); i++) {
        for (int s = i; s; s = (s - 1) & i) {
          if (tot[s] <= x) {
            dp[i] = min(dp[i], dp[i - s] + 1);
          }
        }
      }
      if (dp[(1 << n) - 1] <= k)
        r = x;
      else
        l = x + 1;
    }
    return l;
  }
};

2. 状压dp

跟这个题类似 1655. 分配重复整数

class Solution {
 public:
  int minimumTimeRequired(vector<int>& jobs, int k) {
    int n = jobs.size();
    vector<int> sum(1 << n);
    for (int i = 1; i < (1 << n); i++) {
      for (int j = 0; j < n; j++) {
        if (i & (1 << j)) sum[i] = sum[i ^ (1 << j)] + jobs[j];
      }
    }

    int dp[k][1 << n];
    memset(dp, 0x3f, sizeof dp);
    for (int i = 0; i < (1 << n); i++) {
      dp[0][i] = sum[i];
    }

    for (int i = 1; i < k; i++) {
      for (int j = 0; j < (1 << n); j++) {
        // 枚举子集
        for (int x = j; x; x = (x - 1) & j) {
          dp[i][j] = min(dp[i][j], max(dp[i - 1][j - x], sum[x]));
        }
      }
    }
    return dp[k - 1][(1 << n) - 1];
  }
};

相关文章

网友评论

      本文标题:1723. 完成所有工作的最短时间

      本文链接:https://www.haomeiwen.com/subject/bcnxwltx.html