5101 LCIS 0x50「动态规划」例题
描述
熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了。
小沐沐说,对于两个数列A和B,如果它们都包含一段位置不一定连续的数,且数值是严格递增的,那么称这一段数是两个数列的公共上升子序列,而所有的公共上升子序列中最长的就是最长公共上升子序列了。
奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子序列。不过,只要告诉奶牛它的长度就可以了。数列A和B的长度均不超过3000。
输入格式
第一行N,表示A,B的长度。
第二行,串A。
第三行,串B。
输出格式
输出长度。
样例输入
4 2 2 1 3 2 1 2 3
样例输出
2
数据范围与约定
- 1<=N<=3000,A,B中的数字不超过2^31-1
Contest Hunter - 信息学自助比赛平台
LIS与LCS问题的结合
dp[i][j]表示A1-Ai和B1-Bj中以Bj为结尾的LCIS的长度
那么当Ai != Bj 时 显然dp[i][j] = dp[i-1][j]
当Ai == Bj时 判断1-j中是否有Bk < Bj 取所有可能解的最大值加一
找k时可以for循环跑 那么总的复杂度是n^3
优化的算法是对于每一个i A[i]都没有变化 每次j增加 可能解的数量是递增的
每一次都记录当前j的最大可能解就可用于下一次更新了
“在实现状态转移方程时,要注意观察决策集合的范围随着状态的变化情况。对于“决策集合中的元素只增多不减少的”的情景,就可以像本题一样维护一个变量来记录决策集合的当前信息,避免重复扫描”
很坑的是第三组数据好像个数有问题还是怎么的?反正我输出时多了一个\n就WA,去掉\n就过了
n^2算法
1 //#include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 8 using namespace std; 9 typedef long long int LL; 10 11 const int maxn = 3005; 12 int A[maxn], B[maxn]; 13 int n; 14 int dp[maxn][maxn]; 15 16 int main() 17 { 18 scanf("%d", &n); 19 for(int i = 1; i <= n; i++) 20 scanf("%d", &A[i]); 21 for(int i = 1; i <= n; i++) 22 scanf("%d", &B[i]); 23 24 //memset(dp, 0, sizeof(dp)); 25 for(int i = 1; i <= n; i++){ 26 int val = 0; 27 for(int j = 1; j <= n; j++){ 28 if(A[i] == B[j]){ 29 dp[i][j] = val + 1; 30 } 31 else{ 32 dp[i][j] = dp[i - 1][j]; 33 } 34 if(B[j] < A[i]) val = max(val, dp[i - 1][j]); 35 } 36 } 37 38 int ans = 0; 39 for(int i = 1; i <= n; i++){ 40 ans = max(ans, dp[n][i]); 41 } 42 //cout<<endl; 43 printf("%d", ans); 44 //scanf("%d", &n); 45 return 0; 46 }
n^3算法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 //#include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 8 using namespace std; 9 typedef long long int LL; 10 11 const int maxn = 3005; 12 int A[maxn], B[maxn]; 13 int n; 14 int dp[maxn][maxn]; 15 16 int main() 17 { 18 scanf("%d", &n); 19 for(int i = 1; i <= n; i++) 20 scanf("%d", &A[i]); 21 for(int i = 1; i <= n; i++) 22 scanf("%d", &B[i]); 23 24 //memset(dp, 0, sizeof(dp)); 25 for(int i = 1; i <= n; i++){ 26 for(int j = 1; j <= n; j++){ 27 if(A[i] == B[j]){ 28 for(int k = 0; k < j; k++){ 29 if(B[k] < A[i]) 30 dp[i][j] = max(dp[i - 1][k] + 1, dp[i][j]); 31 } 32 } 33 else{ 34 dp[i][j] = dp[i - 1][j]; 35 } 36 } 37 } 38 39 int ans = 0; 40 for(int i = 1; i <= n; i++){ 41 ans = max(ans, dp[n][i]); 42 } 43 //cout<<endl; 44 printf("%d", ans); 45 //scanf("%d", &n); 46 return 0; 47 }