CH 5101 :LCIS(最长公共上升子序列) 线性DP (“代码等价转化”优化程序)
发布日期:2021-05-20 04:54:42 浏览次数:16 分类:精选文章

本文共 1259 字,大约阅读时间需要 4 分钟。

题目大意

给定两个序列,求他们的最长公共上升子序列

样例

输入样例:42 2 1 32 1 2 3输出样例:2

思路

状态表示
F[i, j] 表示 A1 - Ai 与 B1 - Bj 可以构成的以 Bj 为结尾的LCIS的长度

  1. 当Ai != Bj 时, F[i, j] = F [i - 1, j]
  2. 当Ai = Bj 时, F[i, j] = 前面最长上升公共子序列 + 1

这样用代码表示出来就是

for(int i = 1; i <= n; i++)        for(int j = 1; j <= n; j++)       		 if(a[i] == b[j])            	for(int k = 0; k < j; k++){                   	if(b[k] < a[i])                     	f[i][j] = max(f[i][j], f[i - 1][k] + 1);             }          else f[i][j] = f[i - 1][j];

但是数据范围是3000, O(n ^ 3)时间复杂度显然不行

由于第三重循环是找出前面符合要求的最大的值, 所以我们在第二重循环时把它记录下来就行,相当于把代码做了等价转换,时间复杂度降低了一个量级。
最终代码

#include
#include
#include
#include
using namespace std;const int N = 3010;int a[N], b[N], f[N][N];int n;int main(){ cin >> n; for(int i = 1; i <= n; i++) cin >> a[i]; for(int i = 1; i <= n; i++) cin >> b[i]; for (int i = 1; i <= n; i ++ ){ int val = 0; //if(b[0] < a[i]) val = f[i - 1][0] for (int j = 1; j <= n; j ++ ){ if(a[i] == b[j]) f[i][j] = val + 1; else f[i][j] = f[i - 1][j]; if(b[j] < a[i]) val = max(val, f[i - 1][j]); } } int ans = 0; for(int i = 1; i <= n; i++) ans = max(ans , f[n][i]); cout << ans << endl; return 0;}
上一篇:POJ 3666 Making the Grade 线性DP
下一篇:POJ - 2279 Mr. Young's Picture Permutations 线性DP + 5维DP

发表评论

最新留言

关注你微信了!
[***.104.42.241]2025年05月04日 02时12分18秒