最长递增公共子序列dp(hdu 1423 hdu 4512)
2016-08-10 19:27
330 查看
问题描述:就是求两个数字数组的最长递增公共子序列,o(n*n)的复杂度,结合题目解释
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1423
题意:给两个数字数组,求其最长的递增公共子序列的长度
解释:dp[i][j]是基于dp[i-1][j],就是基于上一个数字的遍历结果的基础进行遍历,解释在代码中,ans的作用是保存1-j的上一行的最长递增公共子序列的长度,从而为下个增的数字服务,当判断是用v_b[j]来判断,因为之前dp[i-1]的情况在j上已经做好了最大优化
代码:
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4512
题意:
有一天,有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h
,吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则称之为完美队形:
1、挑出的人保持他们在原队形的相对顺序不变;
2、左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然,如果m是奇数,中间那个人可以任意;
3、从左到中间那个人,身高需保证递增,如果用H表示新队形的高度,则H[1] < H[2] < H[3] .... < H[mid]。
现在吉哥想知道:最多能选出多少人组成完美队形?
思路:也是把字符串倒过来正反取最长递增公共子序列(见上),但是需要注意的是i<j(保证不重复覆盖的情况),还有,在i+1--j-1的过程中,也许会有一个很大的数,那么也是可以加进去的,从而凑成奇数的递增
代码:
类似题目总结:http://www.cnblogs.com/ziyi--caolu/p/3235229.html
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1423
题意:给两个数字数组,求其最长的递增公共子序列的长度
解释:dp[i][j]是基于dp[i-1][j],就是基于上一个数字的遍历结果的基础进行遍历,解释在代码中,ans的作用是保存1-j的上一行的最长递增公共子序列的长度,从而为下个增的数字服务,当判断是用v_b[j]来判断,因为之前dp[i-1]的情况在j上已经做好了最大优化
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #define N 505 using namespace std; int v_a ; int v_b ; int dp ; int path ; int f ; int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&v_a[i]); } scanf("%d",&m); for(int j=1;j<=m;j++) { scanf("%d",&v_b[j]); } //dp求最长公共递增子序列,以及记录路径 int k=0; int ki,kj,max1=0; for(int i=1;i<=n;i++) { int ans=0;//每次要保证从0长度开始 for(int j=1;j<=m;j++) { dp[i][j]=dp[i-1][j]; //ans保存当前j情况下i-1最优的情况,在i-1上进行改变, //满足这一情况的唯一情况是在存在长度为dp[i-1][j]的递增公共数组并且已v_b[j]为结尾而且v_a[i]>v_b[j],从而保证可以插入v_a[i] //其他情况该判定都为假 //,并且该情况是1-j中最优的(即最长),这很巧妙 if(v_a[i]>v_b[j]&&ans<dp[i][j]) { ans=dp[i][j]; k=j; } if(v_a[i]==v_b[j]) //当两字符相等时进行记录,前面已经保证了存在长度为ans的子数组并且v_a[i]大于该数组的最后一个值,所以必定可以进行插入i { path[i][j]=k; dp[i][j]=ans+1; } if(max1<dp[i][j]) //用于记录路径,当达到最大值时的最大值、行号和列号 { max1=dp[i][j]; ki=i;kj=j; } } } int sum=max1; //输出路径 f[max1--]=kj; int kj2=kj; while(ki&&kj&&max1) //路径的输出,注意第一个匹配字符path[ki][kj]为0,所以要倒过来进行记录 { if(path[ki][kj]>0) { f[max1--]=path[ki][kj]; kj=path[ki][kj]; } ki--; } printf("%d\n",sum); if(t!=0) printf("\n"); /*for(int i=1;i<=sum;i++) { printf("%d ",v_b[f[i]]); }*/ } return 0; }
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4512
题意:
有一天,有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h
,吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则称之为完美队形:
1、挑出的人保持他们在原队形的相对顺序不变;
2、左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然,如果m是奇数,中间那个人可以任意;
3、从左到中间那个人,身高需保证递增,如果用H表示新队形的高度,则H[1] < H[2] < H[3] .... < H[mid]。
现在吉哥想知道:最多能选出多少人组成完美队形?
思路:也是把字符串倒过来正反取最长递增公共子序列(见上),但是需要注意的是i<j(保证不重复覆盖的情况),还有,在i+1--j-1的过程中,也许会有一个很大的数,那么也是可以加进去的,从而凑成奇数的递增
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #define N 250 using namespace std; int dp ; int v ; int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&v[i]); } int max1=0; for(int i=1;i<=n;i++) { int ans=0; for(int j=n;j>i;j--)//必须保证j>i { dp[i][j]=dp[i-1][j]; if(v[i]>v[j]&&ans<dp[i][j]) { ans=dp[i][j]; } if(v[i]==v[j]) { dp[i][j]=ans+1; } if(max1<dp[i][j]*2) { max1=dp[i][j]*2; } for(int k=i+1;k<j;k++) //要保证i+1--j-1 { if(v[k]>v[j]&&max1<dp[i][j]*2+1) //用v[j]来比 { max1=dp[i][j]*2+1; } } } } printf("%d\n",max1); } return 0; }
类似题目总结:http://www.cnblogs.com/ziyi--caolu/p/3235229.html
相关文章推荐
- hdu 1423+hdu 4512 最长公共递增子序列
- HDU 4512 吉哥系列故事——完美队形I LCIS 最长递增公共子序列
- hdu 1423 最长递增公共子序列
- HDU 1423 Greatest Common Increasing Subsequence 最长公共递增序列
- hdu 4512(最长公共递增子序列加强版)
- 最长公共子序列 最长递增子序列(和) 最长递增公共子序列 最长(连续)子序列乘积(HDU)--dp
- hdu 1423 Greatest Common Increasing Subsequence(DP 最长公共上升子序列)
- hdu 4512 吉哥系列故事——完美队形I(最长公共上升序列)
- hdu 1087 Super Jumping! Jumping! Jumping!(dp+最长递增序列)
- Greatest Common Increasing Subsequence hdu1423 最长公共递增子序列
- [HDU 4512] 吉哥系列故事——完美队形I 最长上升公共子序列
- [HDU 1423] Greatest 最长上升公共子序列
- HDU 4512 最长公共上身子序列(加强)
- hdu1159Common Subsequence(DP最长公共递增序列)
- hdu 4512 吉哥系列故事——完美队形I(最长公共上升序列)
- hdu 4512 吉哥系列故事——完美队形I(最长上升公共子序列)
- hdu 1423 Greatest Common Increasing Subsequence(最长公共上升子序列、LCIS)
- hdu 1423 Greatest Common Increasing Subsequence(最长上升公共子序列)
- hdu 1423(最长公共递增子序列)
- HDU 1423 最长上升公共子序列