abc204D 双烤箱烹饪的最短时间

62 阅读1分钟

题面:需要烹饪n道菜,第i道菜耗时t[i],有两个相同的烤箱,一个烤箱同一时间只能烹饪同一道菜。求烹饪完所有菜所需的最短时间?

范围:1 <= n <= 100, 1 <= t[i] <= 1000

分析:01背包变形,需要选出部分菜用烤箱1,其他用烤箱2,两者的最大值为结果,取所有可能的结果的最小值,即为答案。这里dp[i]表示总耗时为i的方案是否可行。

#include <bits/stdc++.h>
const int N = 100000;
int n, a[101], dp[N+1], tot;
void solve() {
    std::cin >> n;
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        tot += a[i];
    }
    dp[0] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = N; j >= a[i]; j--) {
            dp[j] |= dp[j-a[i]];
        }
    }
    int ans = 1E8;
    for (int i = 1; i <= N; i++) {
        if (dp[i]) {
            ans = std::min(ans, std::max(i, tot - i));
        }
    }
    std::cout << ans << "\n";
}
int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

另外,可行性01背包可以用bitset来写,效率更高。

#include <bits/stdc++.h>
int n, a[101], tot;
void solve() {
    std::cin >> n;
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
        tot += a[i];
    }
    std::bitset<100005> dp;
    dp[0] = 1;
    for (int i = 1; i <= n; i++) {
        dp |= dp << a[i];
    }
    int ans = 1E8;
    for (int i = 1; i <= 100000; i++) {
        if (dp[i]) {
            ans = std::min(ans, std::max(i, tot - i));
        }
    }
    std::cout << ans << "\n";
}
int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

标签:背包dp