Jzoj5424 凤凰院凶真

给你两个序列A和B,求出他们的最长公共上升子序列并输出方案

动态规划,我们假设f[i][j]表示A处理到第i位,B处理到第j位时的长度

那么显然,若A[i]=B[j],那么f[i][j]=max{f[i-1][k]}+1,否则f[i][j]=f[i-1][j]

我们再记一个g[i][j]表示f[i][j]是从哪里转移过来的,记上面那个k即可

到时候直接倒序递归按照g[i][j]输出,若g[i][j]=0那么就--i

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int f[5010][5010],g[5010][5010],a[5010],b[5010],n,m;
void print(int i,int j){
	if(j){
		while(i&&!g[i][j]) i--;
		print(i-1,g[i][j]);
		printf("%d ",b[j]);
	}
}
int main(){
	freopen("okarin.in","r",stdin);
	freopen("okarin.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",a+i);
	scanf("%d",&m);
	for(int i=1;i<=m;++i) scanf("%d",b+i);
	for(int k,i=1;i<=n;++i){
		k=0;
		for(int j=1;j<=m;++j){
			f[i][j]=f[i-1][j];
			if(a[i]==b[j]){
				f[i][j]=f[i-1][k]+1;
				g[i][j]=k;
			}
			if(a[i]>b[j]&&f[i-1][k]<f[i-1][j]) k=j;
		}
	}
	int j=0;
	for(int i=m;i;--i)
		if(f[n][i]>f[n][j]) j=i;
	printf("%d\n",f[n][j]);
	print(n,j);
}

posted @ 2017-11-07 19:22  扩展的灰(Extended_Ash)  阅读(89)  评论(0编辑  收藏  举报