Description

【NOIP模拟】千帆渡_动态规划

Solution

比赛的时候就想到了正解,但是因为只剩下一个半小时,要打两题,就匆匆的打了过去,结果拿了零分。
设f[i][j]表示a的前i个与b的第j个匹配的最大值
显然可以f[i][j]=f[i−1][j]
如果a[i]=b[j],如果是从a[k]和b[l]转移过来的,那么b[l]

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=5007;
int i,j,k,l,t,n,m,ans,ans1,ans2;
int f[maxn][maxn],a[maxn],b[maxn],g[maxn][maxn],h[maxn][maxn][2],ans3[maxn];
map<int,int>p;
int main(){
// freopen("fan.in","r",stdin);
// freopen("fan.out","w",stdout);
scanf("%d",&n);
fo(i,1,n)scanf("%d",&a[i]);
scanf("%d",&m);
fo(i,1,m)scanf("%d",&b[i]);
fo(i,1,n){
fo(j,1,m){
f[i][j]=f[i-1][j];
h[i][j][0]=i-1,h[i][j][1]=j;
if(a[i]==b[j]){
if(f[i][j]<f[i-1][g[i][j]]+1){
f[i][j]=f[i-1][g[i][j]]+1;
h[i][j][0]=i-1,h[i][j][1]=g[i][j];
}
}
g[i+1][j]=g[i+1][j-1];
if(f[i][j]>f[i][g[i+1][j]]&&a[i+1]>b[j]){
g[i+1][j]=j;
}
if(f[i][j]>ans)ans1=i,ans2=j;
ans=max(f[i][j],ans);
}
}
printf("%d\n",ans);
while(ans1>0&&ans2>0){
if(!p[b[ans2]])ans3[++ans3[0]]=b[ans2],p[b[ans2]]=1;
int u=ans1,v=ans2;
ans1=h[u][v][0];
ans2=h[u][v][1];
}
fod(i,ans3[0],1)printf("%d ",ans3[i]);
}