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

来源:互联网 发布:知乎 俄罗斯 计算机 编辑:程序博客网 时间:2024/05/21 19:33

This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.
Input
Each sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.
Output
output print L - the length of the greatest common increasing subsequence of both sequences.
Sample Input
151 4 2 5 -124-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;}


阅读全文
0 0
原创粉丝点击