272. 最长公共上升子序列

熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。

小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了。

小沐沐说,对于两个数列 A 和 B,如果它们都包含一段位置不一定连续的数,且数值是严格递增的,那么称这一段数是两个数列的公共上升子序列,而所有的公共上升子序列中最长的就是最长公共上升子序列了。

奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子序列。

不过,只要告诉奶牛它的长度就可以了。

数列 A 和 B 的长度均不超过 3000。

输入格式
第一行包含一个整数 N,表示数列 A,B 的长度。

第二行包含 N 个整数,表示数列 A。

第三行包含 N 个整数,表示数列 B。

输出格式
输出一个整数,表示最长公共上升子序列的长度。

数据范围
1≤N≤3000,序列中的数字均不超过 231−1。

输入样例:
4
2 2 1 3
2 1 2 3
输出样例:
2

三重循环:超时,注意优化。
优化原因: s[i]是一个定值,每次寻找s1[k]<s[i]时都是重复计算。

 #include<iostream>
 #include<stdio.h>
 #include<algorithm>
 #include<string.h>

using namespace std;

typedef long long ll;

int s[3001], s1[3001];
int dp[3001][3001];//表示从s[1]到s[i] 和是s1[i]到 s1[j]的相同的最长上升子序列

int main()
{
	int  n, m;
 
	scanf("%d", &n);
	for (int i = 1;i<=n;i++)
		scanf("%d", &s[i]);
	for (int i = 1;i<=n;i++)
		scanf("%d", &s1[i]);

	int res = 0;

	for (int i = 1;i<=n;i++)
	{
		for (int j = 1;j<=n ;j++)
		{
            if(s[i]==s1[j])
			{
				for (int k = 0;k<j;k++)
				{
					if(s1[k]<s[i])
						dp[i][j] = max(dp[i][j], dp[i - 1][k] + 1);
				}
			}
			else
				dp[i][j] = dp[i-1][j];
		}
	}
	for (int i = 1;i<=n;i++)
		res = max(res, dp[n][i]);

		// for (int i = 1;i<=n;i++)
		// {
		// 	for (int j = 1;j<=n;j++)
		// 		cout << dp[i][j] << " ";
		// 	cout << endl;
		// }
		cout << res << endl;

	return 0;
}
 #include<iostream>
 #include<stdio.h>
 #include<algorithm>
 #include<string.h>

using namespace std;

typedef long long ll;

int s[3001], s1[3001];
int dp[3001][3001];//表示从s[1]到s[i] 和是s1[i]到 s1[j]的相同的最长上升子序列

int main()
{
	int  n, m;
	freopen("11.txt", "r", stdin);
	scanf("%d", &n);
	for (int i = 1;i<=n;i++)
		scanf("%d", &s[i]);
	for (int i = 1;i<=n;i++)
		scanf("%d", &s1[i]);

	int res = 0;

	for (int i = 1;i<=n;i++)
	{
		int Max = 0;//表示当s[i]==s1[j]的时候,此时s1[1......j-1]中最长的上升子序列的长度
		for (int j = 1;j<=n ;j++)
		{
			dp[i][j] = dp[i-1][j];
            if(s[i]==s1[j])
				dp[i][j] = max(dp[i][j], Max+1);
			if(s1[j]<s[i])
				Max = max(Max, dp[i-1][j]);//判断以j结尾 跟新Max.
		}
	}
	for (int i = 1;i<=n;i++)
		res = max(res, dp[n][i]);

		// for (int i = 1;i<=n;i++)
		// {
		// 	for (int j = 1;j<=n;j++)
		// 		cout << dp[i][j] << " ";
		// 	cout << endl;
		// }
		cout << res << endl;

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值