「 COGS 1669 」 神秘的咒语

题目大意

这出题人太凉心,居然给我句鸟语。(连我最爱的OI也被鸟语污染了吗)

下面给大家说说这句鸟语啥意思。不要误会,都是度娘的功劳 QAQ

之前不是给出了两个伪咒语吗。

这句鸟语就是说真正的咒语就是两个伪咒语的最长公共上升子序列的长度

解题思路

开始的时候用二维的 $dp$ 三层循环的做。只有 $40$ 分。这不对啊,为啥?

来看看这组样例

1
1
1
1

不出意外,你的代码会输出 $0$。但是人都能看出答案应该是 $1$ 。问题出在哪呢?

再看一下核心部分的代码

我们发现如果枚举的两个序列的长度都是 $1$ 并且两个数还想等的话。第三重循环就不会进行。

那么我们的 $f$ 数组也就不会更新,这就导致了错误出现。

后来我想了想并没有找到妥帖的解决方法,于是决定写压维优化后的最长公共上升子序列。

大概是这样的

这样就对了。因为 $f$ 数组得到了更新。

附上代码

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int T, m1, m2, a[503], b[503], f[503], Ans;
int main() {
    freopen("codes.in", "r", stdin);
    freopen("codes.out", "w", stdout);
    scanf("%d", &T);
    while (T--) {
        memset(f, 0, sizeof(f));
        Ans = 0;
        scanf("%d", &m1);
        for(int i=1; i<=m1; i++)
            scanf("%d", &a[i]);
        scanf("%d", &m2);
        for(int i=1; i<=m2; i++)
            scanf("%d", &b[i]);
        for(int i=1; i<=m1; i++) {
            int tmp = 0;
            for(int j=1; j<=m2; j++) {
                if(a[i] > b[j]) tmp = max(tmp, f[j]);
                if(a[i] == b[j]) f[j] = tmp + 1;
            }
        }
        for(int i=1; i<=m2; i++)
            Ans = max(f[i], Ans);
        printf("%d
", Ans);
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
原文地址:https://www.cnblogs.com/bljfy/p/9581507.html