Week 10 作业 B - B - LIS & LCS Gym - 277140A

题目描述:

求序列A的最长上升子序列长度和序列AB的最长公共子序列长度

思路:

最长上升序列:定义状态:F[i]表示考虑前i个数得到的最大值,但是用F[i-1]更新F[i]时不知道a[i]选不选;进一步:定义F[i][j]表示考虑前i个数,并且序列以a[j]结尾时得到的最大值,则很显然F[j][j]==F[i][j](i>=j时),并且i不能小于j(因为如果小于就取不到a[j]了),所以第一维是多余的;再进一步:定义F[i]表示以a[i]为结尾的最大值,则F[i]=1+max{F[j],j<i,a[j]<a[i]}

最长公共子序列:定义状态:F[i][j]表示考虑A的前i个数,B的前j个数的最大值;搜索过程:如果A[i]==B[i]则F[i][j]=F[i-1][j-1]+1;如果A[i]!=B[j]则F[i][j]=max(F[i-1][j],F[i][j-1]);边界条件:i<=0或j<=0时,返回0

代码:

#include <cstdio>
#include <iostream>
using namespace std;
const int MAXN=5e3+5;
int A[MAXN],B[MAXN];
int f[MAXN];  //f[i]表示以A[i]为结尾的上升子序列长度
int dp[MAXN][MAXN];	//dp[i][j]表示到A[i]和B[j]时的LCS长度 
int main()
{
	int N,M,LIS=0,LCS=0;
	cin>>N>>M;
	for(int i=1;i<=N;i++)
		scanf("%d",A+i);
	f[1]=1,LIS=1;
	for(int i=2;i<=N;i++)
	{
		for(int j=1;j<i;j++)
		{
			if(A[j]<A[i])
				f[i]=max(f[i],f[j]+1);
		}
		f[i]=max(f[i],1);	//如果没有前面的元素都很大,则就只包括自己,或者直接初始化F[i]=1 
		LIS=max(LIS,f[i]);
	}
	cout<<LIS<<' ';
	
	for(int i=1;i<=M;i++)
		scanf("%d",B+i);
	for(int i=1;i<=N;i++)
		for(int j=1;j<=M;j++)
		{
			if(A[i]==B[j]) dp[i][j]=dp[i-1][j-1]+1;
			else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
		}
	cout<<dp[N][M]<<endl;
}

  

posted @ 2020-05-20 12:11  菜鸡今天学习了吗  阅读(119)  评论(0编辑  收藏  举报