zoukankan      html  css  js  c++  java
  • CF10D LCIS

    洛咕

    POJ

    题意:求两个数列的最长公共上升子序列.输出长度和任意一种方案.

    这道题我真的做到崩溃,搞了几个小时,原本在洛咕上的方法在POJ上全WA了.个人认为是输出方案的问题.

    分析:设(f[i][j])表示(A)序列前i个和(B)序列前j个构成的最长公共上升子序列的长度.

    (A[i])不等于(B[j])时,(f[i][j]=f[i-1][j])

    (A[i]=B[j])时,(f[i][j]=max(f[i][j],f[i-1][t]+1)),t为最长公共上升子序列结尾的元素的位置.

    因为要输出方案,所以在每次更新序列时,再开一个数组记录一下,最后递归输出方案.

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    const int N=505;
    int a[N],b[N],f[N][N],g[N][N];
    inline void print(int n,int pos){
        if(!pos)return;
        print(n,g[n][pos]);
        printf("%d ",b[pos]);
    }
    int main(){
        int n=read();for(int i=1;i<=n;i++)a[i]=read();
        int m=read();for(int i=1;i<=m;i++)b[i]=read();
        for(int i=1,t=0;i<=n;i++,t=0)
        	for(int j=1;j<=m;j++){
    	    	f[i][j]=f[i-1][j];g[i][j]=g[i-1][j];
    	    	if(a[i]==b[j]&&f[i-1][t]+1>f[i][j]){
            		f[i][j]=f[i-1][t]+1;
            		g[i][j]=t;
    	    	}
    	    	if(a[i]>b[j]&&f[i-1][t]<f[i-1][j])t=j;
    		}
        int pos=0;
        for(int i=1;i<=m;i++)if(f[n][i]>f[n][pos])pos=i;
        printf("%d
    ",f[n][pos]);
        print(n,pos);puts("");
        return 0;
    }
    
    
    

    因为(f[i][j])都是由(f[i-1][j])转移而来的,所以可以滚掉第一维数组,优化空间.

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
       int s=0,w=1;char ch=getchar();
       while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
       while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
       return s*w;
    }
    const int N=505;
    int a[N],b[N],f[N],g[N];
    inline void print(int pos){
        if(!pos)return;
        print(g[pos]);
        printf("%d ",b[pos]);
    }
    int main(){
        int n=read();for(int i=1;i<=n;i++)a[i]=read();
        int m=read();for(int i=1;i<=m;i++)b[i]=read();
        for(int i=1,t=0;i<=n;i++,t=0)
        	for(int j=1;j<=m;j++){
            	if(a[i]==b[j]&&f[t]+1>f[j]){
            		f[j]=f[t]+1;
            		g[j]=t;
            	}
            	if(a[i]>b[j]&&f[t]<f[j])t=j;
        	}
        int pos=0;
        for(int i=1;i<=m;i++)if(f[i]>f[pos])pos=i;
        printf("%d
    ",f[pos]);
        print(pos);puts("");
        return 0;
    }
    
    
    

    然后我又把递归输出方案改成了栈来实现,就在POJ上过了,真的好玄学啊.

    //#include<bits/stdc++.h>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    inline int read(){
        int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    const int N=505;
    int a[N],b[N],st[N],f[N][N],g[N][N];
    int main(){
    		memset(g,-1,sizeof(g));
    		int n=read();for(int i=1;i<=n;i++)a[i]=read();
    		int m=read();for(int i=1;i<=m;i++)b[i]=read();
    		for(int i=1,t=0;i<=n;i++,t=0){
    	    	for(int j=1;j<=m;j++){
    				f[i][j]=f[i-1][j];
    					if(a[i]==b[j]&&f[i-1][t]+1>f[i][j]){
    		    		f[i][j]=f[i-1][t]+1;
    		    		g[i][j]=t;
    				}
    				if(a[i]>b[j]&&f[i-1][t]<f[i-1][j])t=j;
    	    	}
    		}
    		int pos=0;
    		for(int i=1;i<=m;i++)
    	    	if(f[n][i]>f[n][pos])pos=i;
    		printf("%d
    ",f[n][pos]);
    		if(f[n][pos]<=0)return 0;
    		int tmp=pos;
    		for(int i=n;i>=1;i--)
            	if(g[i][tmp]!=-1)
            		st[++st[0]]=a[i],tmp=g[i][tmp];
    		for(int i=st[0];i>=2;i--)printf("%d ",st[i]);
    		printf("%d 
    ",st[1]);
        return 0;
    }
    
  • 相关阅读:
    ZOJ 3876 May Day Holiday 蔡勒公式
    ZOJ 3870 Team Formation 贪心二进制
    ZOJ 3872 计算对答案的贡献
    Codeforces Round #324 (Div. 2)C. Marina and Vasya set
    Jquery前端分页插件pagination使用
    最简单的混合开发教程资料汇总
    最简单的混合开发教程资料汇总
    2018年各大互联网前端面试题二(滴滴打车)
    2018年各大互联网前端面试题二(滴滴打车)
    【福利】小程序开发资源干货汇总
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10886066.html
Copyright © 2011-2022 走看看