CF933A
由于 \(a_i \le 2\),那么答案的序列必定为 \([1, 1, \ldots][2, 2, \ldots][1, 1, \ldots][2, 2, \ldots]\)(每一段都可以为空),接着我们便可以翻转第二段和第三段子序列,得到最佳答案。
做法:
很简单的一个线性 dp。
状态定义:我们定义 \({dp_i}_j\) 为现在到了第 \(i\) 个数,第 \(j\) 段子序列。
状态转移:
\[\begin{cases}
{dp_i}_0 = {dp_{i - 1}}_0 + [a_i = 1]\\
{dp_i}_1 = \max\{{dp_i}_0, {dp_{i - 1}}_1 + [a_i = 2]\}\\
{dp_i}_2 = \max\{{dp_i}_1, {dp_{i - 1}}_2 + [a_i = 1]\}\\
{dp_i}_3 = \max\{{dp_i}_2, {dp_{i - 1}}_3 + [a_i = 2]\}\\
\end{cases}
\]
时间复杂度 \(\mathcal{O}(N)\)。
代码:
#include <bits/stdc++.h>
const int N = 2e3 + 5, M = 7, K = 27;
using namespace std;
int n;
int d[N], f[5];
signed main()
{
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> d[i];
for (int i = 1; i <= n; i ++ )
{
f[1] += (d[i] == 1);
f[2] = max(f[1], f[2] + (d[i] == 2));
f[3] = max(f[2], f[3] + (d[i] == 1));
f[4] = max(f[3], f[4] + (d[i] == 2));
}
cout << f[4];
}