【NOIP模拟】千帆渡

Description

【NOIP模拟】千帆渡_第1张图片

Solution

比赛的时候就想到了正解,但是因为只剩下一个半小时,要打两题,就匆匆的打了过去,结果拿了零分。
f[i][j]aibj
显然可以 f[i][j]=f[i1][j]
如果a[i]=b[j],如果是从a[k]和b[l]转移过来的,那么b[l]

Code

#include
#include
#include
#include
#include
#include
#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][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]);
}

你可能感兴趣的:(noip,DP)