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];
}
posted @ 2023-07-19 07:52  恋暗  阅读(18)  评论(0)    收藏  举报