[CODEVS] 2185 最长公共上升子序列
2018-03-29 23:35
316 查看
把LIS和LCS的状态结合,f[i][j]表示 a的前i位,和b以b[j]结尾的子序列 的LICS。
a[i]==b[j] 那么f[i][j]=max{f[i-1][k]}+1 其中1<=k<j,满足b[k]<b[j]
a[i] != b[j] 那么f[i][j]=f[i-1][j]
对此我的理解是 ,i递增是转移的深入,j遍历是保证递增的性质。
定义决策集合为[1,j-1]中b[j]<b[i]的值,我们需要最大值。
对于内层循环,外层提供的i是固定的,而a[i]==b[i],所以在集合内的元素不会退出,也就是前面的可以为后面服务。
而对于j-1位转移到了j位,决策集合只需要最大值,那么判断b[j]和mx的关系决定是否加入即可,可以省下一层找最大值的循环,
a[i]==b[j] 那么f[i][j]=max{f[i-1][k]}+1 其中1<=k<j,满足b[k]<b[j]
a[i] != b[j] 那么f[i][j]=f[i-1][j]
对此我的理解是 ,i递增是转移的深入,j遍历是保证递增的性质。
定义决策集合为[1,j-1]中b[j]<b[i]的值,我们需要最大值。
对于内层循环,外层提供的i是固定的,而a[i]==b[i],所以在集合内的元素不会退出,也就是前面的可以为后面服务。
而对于j-1位转移到了j位,决策集合只需要最大值,那么判断b[j]和mx的关系决定是否加入即可,可以省下一层找最大值的循环,
//Stay foolish,stay hungry,stay young,stay simple #include<iostream> using namespace std; int f[3001][3001]; int a[3001],b[3001]; int n,m; int main(){ cin>>n; m=n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=m;i++) cin>>b[i]; for(int i=1;i<=n;i++){ int mx=0; // if(b[0]<a[i]) mx=f[i-1][0]; for(int j=1;j<=m;j++){ if(a[i]==b[j]) f[i][j]=mx+1; else f[i][j]=f[i-1][j]; if(b[j]<a[i]) mx=max(mx,f[i-1][j]); } } int ans=0; for(int i=1;i<=m;i++) ans=max(ans,f [i]); cout<<ans<<endl; return 0; }
相关文章推荐
- codevs 2185 最长公共上升子序列
- Codevs2185 最长公共上升子序列
- 最长公共上升子序列(codevs 2185)
- 线性DP LCIS(最长公共上升子序列)CODE(VS)
- CODE[VS] 最长公共上升子序列(LCIS)(序列型DP)
- Codevs 2185 最长公共上升子序列 LCIS
- codevs 2188 最长上升子序列(DP)
- codevs 2188 最长上升子序列
- [CodeVS 2185] 最长公共上升子序列:DP
- Code[vs] 1576 最长严格上升子序列
- 【基础练习】【线性DP】codevs1576 最长严格上升子序列题解
- codevs 1576最长严格上升子序列
- [codevs1576] 最长严格上升子序列
- codevs-3955 最长不上升子序列
- CODEVS1576最长严格上升子序列
- 【基础练习】【线性DP】codevs1576 最长严格上升子序列题解
- 【基础练习】【二分】codevs2188 最长上升子序列(限定元素)题解
- codevs 1576 最长严格上升子序列
- Codevs P2188 最长上升子序列
- CODEVS 1576最长严格上升子序列