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);
}