$\Huge\text{Market Solution}$
----------
:::info
🔗 Links:
📌 Tags: `DP`
✍ Writer: Hoàng Việt
📄 Content:
[TOC]
:::
---------
## Thuật toán
Cho $dp[i][S]$ lưu các giá trị $true/false$, với $dp[i][S]$ == $true$ thì có thể chọn ra được một tập con có tổng đúng bằng $S$ khi xét các phần tử từ $1$ đến $i$ ($i$ phần tử đầu tiên).
Bài toán cơ sở: $dp[0][0] = true$.
Có hai trường hợp chuyển trạng thái:
- $dp[i][S]$ |= $dp[i - 1][S]$, trường hợp không sử dụng phần tử thứ $i$.
- $dp[i][S]$ |= $dp[i - 1][S - a[i]]$, trường hợp có sử dụng phần tử thứ $i$.
Số lượng tổng tối đa có thể tạo được là số lượng $dp[n][S]$ == $true$.
Độ phức tạp $O(n^2 * a_i)$.
Code mẫu:
``` cpp=
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
using namespace std;
const int MAXN = 510;
const int INF = 1e9;
const int MOD = 1e9 + 7;
const int base = 28;
void solve() {
int n;
cin >> n;
int a[n + 1], S = 0;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
S += a[i];
}
bool dp[n + 1][S + 1];
memset(dp, false, sizeof(dp));
dp[0][0] = 1;
for(int i = 1; i <= n; i ++)
for(int j = 0; j <= S; j ++) {
dp[i][j] |= dp[i - 1][j];
if(j >= a[i] && j - a[i] <= S)
dp[i][j] |= dp[i - 1][j - a[i]];
}
int ans = 0;
for(int i = 1; i <= S; i ++)
ans += dp[n][i];
cout << ans << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
// int tt;
// cin >> tt;
// while(tt --)
solve();
return 0;
}
```
------------