洛谷P1410 子序列 题解 动态规划
题目链接:https://www.luogu.com.cn/problem/P1410
题目大意:
给定一个长度为N(N为偶数)的序列,问能否将其划分为两个长度为N/2的严格递增子序列。
解题思路:
定义 \(f_{i,j}\) 表示前 \(i\) 个数,\(a_i\) 所在的子序列长度为 \(j\) 的情况下,另外一个子序列的最后一个元素的最小值。
初始时 \(f_{1,1} = 0\),其他状态设为 \(inf\)。
最终只需要判断 \(f_{n,n/2}\) 是否为 \(inf\) 即可。
状态转移方程:
if (a[i-1] < a[i]) f[i][j] = min(f[i][j], f[i-1][j-1]);
if (f[i-1][i-j] < a[i]) f[i][j] = min(f[i][j], a[i-1]);
示例代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2002;
int n, a[maxn], f[maxn][maxn];
int main() {
while (~scanf("%d", &n)) {
for (int i = 1; i <= n; i ++) scanf("%d", a+i);
memset(f, 0x3f, sizeof(f));
f[1][1] = 0;
for (int i = 2; i <= n; i ++) {
for (int j = 1; j <= i && j <= n/2; j ++) {
if (a[i-1] < a[i]) f[i][j] = min(f[i][j], f[i-1][j-1]);
if (f[i-1][i-j] < a[i]) f[i][j] = min(f[i][j], a[i-1]);
}
}
puts( f[n][n/2] == 0x3f3f3f3f ? "No!" : "Yes!" );
}
return 0;
}