题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1423
思路分析:[问题定义]给定两个序列A[0, 1,..., m]和B[0, 1, ..., n],要求这两个序列的最长公共上升子序列;
该问题为动态规划问题,可以采用与求最长公共子序列与最长上升子序列相同的思想来思考求出动态规划方程;
定义状态dp[i][j] 为序列A的前 i 个数字与序列B 的最长公共上升子序列,且该最长公共上升子序列以序列B的第 j 个数字为最后一个数字;
则可以推导出动态转移方程为:
if A[i] != B[j], dp[i][j] = dp[i-1][j];
if A[i] == B[j], dp[i][j] = MAX{dp[i-1][k]} + 1, 0 <= k <j && B[k] < B[j];
代码如下:
#include <iostream> using namespace std; const int MAX_N = 500 + 10; int dp[MAX_N][MAX_N]; int num_a[MAX_N], num_b[MAX_N]; int main() { int test_case, ans; int len_a, len_b; scanf("%d", &test_case); while (test_case--) { scanf("%d", &len_a); for (int i = 1; i <= len_a; ++i) scanf("%d", &num_a[i]); scanf("%d", &len_b); for (int i = 1; i <= len_b; ++i) scanf("%d", &num_b[i]); ans = 0; memset(dp, 0, sizeof(dp)); for (int i = 1; i <= len_a; ++i) { for (int j = 1; j <= len_b; ++j) { if (num_a[i] != num_b[j]) dp[i][j] = dp[i - 1][j]; else { int max = 0; for (int k = 1; k < j; ++k) { if (num_b[j] > num_b[k] && dp[i - 1][k] > max) max = dp[i - 1][k]; } dp[i][j] = max + 1; } } } for (int i = 0; i <= len_a; ++i) { if (dp[len_a][i] > ans) ans = dp[len_a][i]; } printf("%d ", ans); if (test_case) printf(" "); } return 0; }