您的位置:首页 > 其它

hdu 1423 dp 求最长公共上升子序列

2017-09-23 09:27 323 查看
This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.

InputEach sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.
Outputoutput print L - the length of the greatest common increasing subsequence of both sequences.
Sample Input
1

5
1 4 2 5 -12
4
-12 1 2 4


Sample Output
2


题意:是求最长公共上升子序列 

最长公共上上升子序列的详解:http://www.cnblogs.com/wd-one/p/4470844.html

思路:用动态规划:

dp[i][j]存的是当a数组长度为i时,b数组长度为j时且b[j]为结尾的最长公共上升子序列;

代码里有思路和解释:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

int dp[550][550];//dp[i][j] 存的是当a数组长度为i时,b数组长度为j时且b[j]为结尾的
int n,m;		//最长公共上升子序列;
int a[550],b[550];

// 当a[i]!=b[j] 时,dp[i][j]=dp[i-1][j];
//因为 d[i][j] 是以 b[j] 为结尾的LCIS,
//如果 d[i][j] > 0 那么就说明 a[1] .... a[i] 中必然有一个元素 a[k] 等于 b[j]
// 当a[i]==b[j] 时,d[i][j]=max(dp[i-1][k])+1;其中b[j]>b[k];
////只有当a[i] > b[j]时,才更新Max, 保证了所求序列是上升的。
int main()
{
int i,j,k,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(i=1;i<=m;i++)
scanf("%d",&b[i]);

int Max,M=0;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
Max=0;
for(j=1;j<=m;j++)
{
if(a[i]!=b[j])
{
dp[i][j]=dp[i-1][j];
if(a[i]>b[j]&&dp[i-1][j]>Max)
{
Max=dp[i-1][j];
}
}
//要理解为啥a[i]>b[j]时;
// a[i] 是外层循环,当和内层循环b[j]相等时,这一步是为了在找出前面
// 小于b[j] 的最大值 ,就是为啥是dp[i-1][j]>Max而不是dp[i][j],因为要找以b[j]结尾的最长公共上升子序列,当
//b[j]==a[i] ,也就是找a[i]的,若写dp[i][j]的话,就把a[i]也算进去了,a[i] 只能结尾于最长公共子序列的末尾;
else
{
dp[i][j]=Max+1;
}
M=max(M,dp[i][j]);
}
}
printf("%d\n",M);
if(t) printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: