洛谷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;
}
posted @ 2020-08-18 13:29  quanjun  阅读(200)  评论(0编辑  收藏  举报