AK_heaven
2024-09-15 23:02:21
[ABC204D] Cooking
动态规划题目应当从转移可行性入手,我们考虑这道题目,由于物品没有顺序,又不适用状态压缩 DP,所以只有考虑贪心或者其他转移方式的 DP。
我们发现
发现不行,这时候我们考虑 DP 换键,我们把状态设计为
这样期望得分
第一维可以进行滚动,最终空间复杂度降低到
The code
#include <bits/stdc++.h>
#define L(i, a, b) for(int i = (a); i <= (b); i++)
#define R(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
using namespace std;
const int N = 1e5 + 10;
int ast, bst, n, a[N], F[2][N];
int main() {
cin >> n;
L(i, 1, n) cin >> a[i];
memset(F, 0x3f, sizeof(F));
F[0][0] = 0;
L(i, 1, n) {
L(j, 0, N-1)
if(j >= a[i]) F[i % 2][j] = min(F[(i-1) % 2][j]+a[i], F[(i-1) % 2][j-a[i]]);
else F[i % 2][j] = F[(i-1) % 2][j]+a[i];
}
int Ans = N*100;
L(i, 0, N-1)
Ans = min(Ans, max(F[n % 2][i], i));
cout << Ans << '\n';
return 0;
}
如果
我们发现其实我们只需要求出左炉的所有组合可以凑出来的数字即可,
如果直接暴力转移,同样会超时,这时候我们需要进行一下 Bitset 优化。
时间复杂度
The code
#include <bits/stdc++.h>
#define L(i, a, b) for(int i = (a); i <= (b); i++)
#define R(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
using namespace std;
const int N = 1e5 + 10;
bitset<N> S; int n, x, s;
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
S[0] = 1;
cin >> n;
L(i, 1, n) cin >> x, S = S | (S << x), s += x;
int ans = 1e9;
L(i, 0, s/2)
if(S[i]) ans = min(ans, max(i, s-i));
cout << ans << '\n';
return 0;
}