最长公共上升子序列(LCIS)学习小记 Hdu 1423 + Poj 2127 (LCIS路径输出)

来源:互联网 发布:seo网站排名优化工具 编辑:程序博客网 时间:2024/04/29 17:11

LCS和LIS的结合,时间复杂度O(m*n),如果不要求路径输出 (如 Hdu 1426) 则空间复杂度O(n),若要求路径输出 (如 Poj 2127)  则空间复杂度O(n^2) 。

学习的时候最早读的是《动态规划中的提纯》,果断没看懂。。。。

参考了以下两篇博文后终于理解了算法的思想。


Hdu 1423 动态规划—最长公共上升子序列 - 诺小J - 博客园
http://www.cnblogs.com/nuoyan2010/archive/2012/10/17/2728289.html

【经典问题】最长公共上升子序列 | Clarkok
http://www.clarkok.com/blog/?p=353


贴上自己的代码:

Hdu 1423

#include <cstdio>#include <iostream>using namespace std;int data1[505],data2[505];int dp[505];  //dp[j]为序列2前j个元素与序列1构成的最长公共上升子序列的长度int main (){#ifdef ONLINE_JUDGE    #else      freopen("read.txt","r",stdin);  #endif int T;scanf("%d",&T);while (T--){int n,m,i;scanf("%d",&n);for (i=1;i<=n;i++)scanf("%d",&data1[i]);scanf("%d",&m);for (i=1;i<=m;i++)scanf("%d",&data2[i]);memset(dp,0,sizeof(dp));for (i=1;i<=n;i++)for (int j=1,temp=0;j<=m;j++)if (data2[j]<data1[i] && dp[j]>temp)temp=dp[j];else if (data1[i]==data2[j])dp[j]=temp+1;int ans=-1;for (i=1;i<=m;i++)if (dp[i]>ans)ans=dp[i];printf("%d\n",ans);if (T)printf("\n");}return 0;    }

Poj 2127

#include <cstdio>#include <iostream>#define max(x,y) ((x)>(y)?(x):(y)) using namespace std;int data1[505],data2[505];int dp[505],pre[505][505];  //dp[j]为序列2前j个元素与序列1构成的最长公共上升子序列的长度int num[505];int main (){int n,m,i;while (~scanf("%d",&n)){for (i=1;i<=n;i++)scanf("%d",&data1[i]);scanf("%d",&m);for (i=1;i<=m;i++)scanf("%d",&data2[i]);memset(dp,0,sizeof(dp));memset(pre,-1,sizeof(pre));int x=0,y=0,ans=-1;for (i=1;i<=n;i++){int temp=0,last=0;for (int j=1;j<=m;j++){if (data2[j]<data1[i] && dp[j]>temp){temp=dp[j];last=j;}if (data1[i]==data2[j]){dp[j]=temp+1;pre[i][j]=last;}if (dp[j]>ans){ans=dp[j];x=i;    //最终结果x不一定等于n!y=j;}}}printf("%d\n",ans);int cas=ans;for (i=ans;i>=1;i--)        {            num[i]=data2[y];            y=pre[x--][y];            while (data1[x]!=data2[y])                x--;        }for (i=1;i<=cas;i++)printf (i==cas?"%d\n":"%d ",num[i]);}return 0;    }