题意:LCIS(Longest Common Increasing Subsequence) 最长公共上升子序列
分析:a[i] != b[j]: dp[i][j] = dp[i-1][j]; a[i]==b[j]: dp[j]=max(dp[j],dp[k]); (1<=k<j&&b[k]<b[j]) 打印路径时按照b[i]来输出
收获:理解不是很深入,推荐资料: 最长公共上升子序列(LCIS)的O(n^2)算法 最长公共上升子序列的另一个O(mn)的算法
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <map> using namespace std; const int N = 5e2 + 10; const int INF = 0x3f3f3f3f; int a[N], b[N], dp[N][N], fx[N][N], fy[N][N]; int n, m; bool fir; void print(int x, int y, int last) { //bool fir; if (x == 0 || y == 0) return ; print (fx[x][y], fy[x][y], y); if (y != last) { if (fir) printf ("%d", b[y]), fir = false; else printf (" %d", b[y]); } } void LCIS(void) { memset (dp, 0, sizeof (dp)); memset (fx, 0, sizeof (fx)); memset (fy, 0, sizeof (fy)); int sx = 0, sy = 0; int ret = 0, k = 0; for (int i=1; i<=n; ++i) { k = 0; for (int j=1; j<=m; ++j) { dp[i][j] = dp[i-1][j]; //以a[]为主循环,每个a[i],去找每个b[j] fx[i][j] = i - 1; fy[i][j] = j; if (a[i] == b[j] && dp[i][j] < dp[i][k] + 1) { //满足LCS dp[i][j] = dp[i][k] + 1; //在1~j-1找到b[k]<a[i],满足LIS,在b[k]上更新dp fx[i][j] = i; fy[i][j] = k; } else if (a[i] > b[j] && dp[i][j] > dp[i][k]) k = j; //找到最优的k if (ret < dp[i][j]) { ret = dp[i][j]; //更新所有dp中的最大值 sx = i, sy = j; } } } printf ("%d ", ret); fir = true; print (sx, sy, -1); puts (""); } int main(void) { while (scanf ("%d", &n) == 1) { for (int i=1; i<=n; ++i) scanf ("%d", &a[i]); scanf ("%d", &m); for (int i=1; i<=m; ++i) scanf ("%d", &b[i]); LCIS (); } return 0; }