题面:需要烹饪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