UVA10066 【The Twin Towers】

题目大意:给定两个序列,求他们的最长公共子序列,题目多测。

考虑到这道题的数据范围比较小,\(N\leq100\),所以我们采用\(n^2\)的朴素方法即可。你觉得我会告诉你我不会nlogn的做法吗?!

我们定义状态\(f[i][j]\)表示第一个串枚举到第\(i\)位,第二个串枚举到第\(j\)位时的最长公共子序列长度。

考虑如何转移,我们分情况讨论:

  • \(a[i-1]==b[i-1]\)时,考虑更新公共元素,显然此时的\(f[i][j]=f[i-1][j-1]+1\)

  • 否则,我们考虑继承,那么\(f[i][j]\)就应取\(f[i-1][j]\)\(f[i][j-1]\)中最大值。

由于我们转移的时候需要枚举串\(a\)和串\(b\)的长度,所以这个的复杂度是\(O(n^2)\)的。

最后,注意你的输出格式……

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#define max(a, b) ((a) > (b) ? (a) : (b))
// 对,我觉得using namespace std慢,所以没写
int f[110][110], a[110], b[110];

int main() {
    std::ios::sync_with_stdio(0); // 关闭cin的同步缓存流,加快速度
    int n, m, cnt = 0;
    while (std::cin >> n >> m && (n != 0 || m != 0)) {
        for (int i = 0; i < n; i++) std::cin >> a[i];
        for (int i = 0; i < m; i++) std::cin >> b[i];
        memset(f, 0, sizeof(f));
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++) {
                if (a[i - 1] == b[j - 1]) f[i][j] = f[i - 1][j - 1] + 1;
                else f[i][j] = max(f[i - 1][j], f[i][j - 1]); //核心转移方程
        }
        printf("Twin Towers #%d\nNumber of Tiles : %d\n", ++cnt, f[n][m]);
        puts(""); // 注意输出格式……
    }
    return 0;
}

完结撒花(*๓´╰╯`๓)

posted @ 2019-10-25 14:52  Hydrogen_Helium  阅读(96)  评论(0编辑  收藏  举报