您的位置:首页 > 产品设计 > UI/UE

POJ 2127 Greatest Common Increasing Subsequence【最长公共递增子序列】

2012-08-25 09:06 447 查看
题意: 给两个数组,求最长公共递增子序列。

分析: dp[i,j]表示a串前i个字符,b串前j个字符组成的,并且以b[j]为结尾的最长的LCIS,

转移方程:
dp[i,j]=dp[i-1,j]; //a[i]与b[j]不等
dp[i,j]=dp[i-1,k]+1; (1<=k<=j-1) //a[i]与b[j] 相等
以上转移方程是O(n^3)时间复杂度

   优化:
由于最外层循环是 i,第二层是 j,循环 j 的时候,实际上同时找出dp[i-1,k] 的最大值MAX

方法:循环 j 的同时,若a[i]>b[j],更新MAX (因为当且仅当a[i]>b[j]时,后边循环 j 时可能用到这个决策来转移)

若a[i] = b[j] 则用MAX+1更新 dp[i,j],记录路径。

#include<stdio.h>
#include<string.h>
#define maxn 505
#define clr(x)memset(x,0,sizeof(x))
int a[maxn];
int b[maxn];
int dp[maxn][maxn];
int path[maxn][maxn];
int ans[maxn];
int main()
{
int l1,l2,i,j,ai,aj,mx,mj,res,tmp;
while(scanf("%d",&l1)!=EOF)
{
res=0;
clr(dp);
clr(path);
for(i=1;i<=l1;i++)
scanf("%d",&a[i]);
scanf("%d",&l2);
for(i=1;i<=l2;i++)
scanf("%d",&b[i]);
for(i=1;i<=l1;i++)
{
mx=0;
for(j=1;j<=l2;j++)
{
dp[i][j]=dp[i-1][j];
path[i][j]=-1;
if(b[j]<a[i]&&dp[i-1][j]>mx)
{
mx=dp[i-1][j];
mj=j;
}
else if(a[i]==b[j])
{
dp[i][j]=mx+1;
path[i][j]=mj;
}
if(res<dp[i][j])
{
res=dp[i][j];
ai=i;
aj=j;
}
}
}
printf("%d\n",res);
tmp=res;
while(tmp)
{
if(path[ai][aj]>-1)
{
ans[tmp--]=b[aj];
aj=path[ai][aj];
}
ai--;
}
for(i=1;i<=res;i++)
printf("%d%c",ans[i],i==res?'\n':' ');

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐