12.49 P6228 汤姆的餐厅 题解

P6228 汤姆的餐厅

题面

Tom's Kitchen 是一家非常受欢迎的餐厅,其受欢迎的原因之一是每份菜都由至少 $ K $ 名厨师进行准备。今天有 $ N $ 份菜需要准备,第 $ i $ 份菜的准备时间是 $ A_i $ 小时。

Tom 可以雇佣 $ M $ 名厨师,厨师 $ j $ 最多可以工作 $ B_j $ 小时。此外,即使厨师 $ j $ 的工作时间不到 $ B_j $ 小时,他也会得到工作 $ B_j $ 小时的报酬。一名厨师可以花不同的时间准备不同的菜,但是每一道菜都需要由至少 $ K $ 名厨师准备,并且他们花的时间总和恰好为 $ A_i $。当一名厨师准备菜品时,他总会花正整数小时。

Tom 需要一套最优的雇佣厨师方案,以使得厨师不工作就获得报酬的小时数(即所有雇佣厨师的总工作时间上限与准备所有菜的总时间之差)尽可能小。

$ 1 \leq N,M,K,A_i,B_j \leq 300 $。

题解

拆贡献好题

发现这道题对于每道菜有两个限制

  • \(k\) 个厨师做
  • 一共做 \(a_i\) 时间

那么我们可以考虑分拆每个厨师的贡献,分为总价值 \(b_i\) 和基础价值 \(min (b_i, n)\)

这样就可以转化为一个背包模型,设 \(f[i][j]\) 表示考虑了前 \(i\) 个人,总价值为 \(j\) 的情况下的最大基础价值

转移方程:\(f[i][j] = max (f[i - 1][j], f[i - 1][j - b_i] + min (n, b_i))\)

时间复杂度为 \(O(m \sum b_i)\) ,空间复杂度滚动数组后为 \(O(\sum b_i)\)

code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

const int N = 1e5 + 10;

int n, m, k;
int a[N], b[N];

// f[i][j] : 考虑前 i 个人,总价值为 j 的情况下,最大基础价值
int f[2][90010];


int main () {

    string no_solution = "Impossible";

    cin >> n >> m >> k;
    int suma = 0, sumb = 0;
    bool fn = 0;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        if (a[i] < k) {
            fn = 1;
        }
        suma += a[i];
    }

    for (int i = 1; i <= m; i++) {
        cin >> b[i];
        sumb += b[i];
    }

    if (fn) {
        cout << no_solution << endl;
        return 0;
    }

    //这里要将不合法状态初始化为 -inf ,因为我们要求 f[i][j] 为总价值为 j 而不能小于 j, 也就是保证背包要装满
    memset (f, -0x3f, sizeof f);
    f[0][0] = 0;

    for (int i = 1; i <= m; i++) {
        int now = i & 1, la = now ^ 1;
        for (int j = 0; j < b[i]; j ++) {
            f[now][j] = f[la][j];
        }
        for (int j = b[i]; j <= sumb; j++) {
            f[now][j] = max (f[la][j], f[la][j - b[i]] + min (n, b[i]));
        }
    }

    for (int i = suma; i <= sumb; i ++) {
        if (f[m & 1][i] >= n * k) {
            cout << i - suma << endl;
            return 0;
        }
    }

    cout << no_solution << endl;

    return 0;
}
posted @ 2025-08-22 09:08  michaele  阅读(3)  评论(0)    收藏  举报