zoukankan      html  css  js  c++  java
  • CF10D-LCIS题解--线性DP+打印方案

    题目链接:

    https://www.luogu.org/problemnew/show/CF10D

    方法一

    分析

    (LCS)(LIS)已经成烂大街的知识了,可是当这两个合并起来成为(LCIS),解决的方式方法也多了起来.

    首先有种最朴素的(O(N^4))方法,(f[i][j])表示A串第(i)个字母和B串第(j)个字母结尾的状态中(LCIS)的长度,那么

    那么如果(a[i]==b[j],f[i][j]=max_{0<=k<j且b[k]<a[i](b[j])}(f[i-1][k])+1)

    否则(f[i][j]=f[i-1][j])

    但是这种方法怎么打印方案呢?我们用(path[j][len[j]])表示以(j)结尾的(LCIS)方案,(len[j])指的是以(j)结尾的(LCIS)长度

    这样我们从(k)更新到(j)时,首先将(path[k][len[k]])全部复制到(path[j][len[j]]);

    然后(len[j]=len[k]+1,path[j][len[j]]=b[j])

    跑时950+ms

    代码

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cctype>
    #include <queue>
    #include <vector>
    #define ll long long 
    #define ri register int 
    using std::max;
    using std::min;
    using std::swap;
    template <class T>inline void read(T &x){
    	x=0;int ne=0;char c;
    	while(!isdigit(c=getchar()))ne=c=='-';
    	x=c-48;
    	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    	x=ne?-x:x;return ;
    }
    const int maxn=505;
    const int inf=0x7fffffff;
    int n,m,a[maxn],b[maxn],f[maxn][maxn],len[maxn];
    int path[maxn][maxn];
    void print(int x){
     	for(ri i=1;i<=len[x];i++)printf("%d ",path[x][i]);
     	puts("");
    	return ;
    }
    int main(){
    	int x,y,z;
    	int ans=-inf,ed=0;
    	read(n);
    	for(ri i=1;i<=n;i++){read(a[i]);}
    	read(m);
    	for(ri i=1;i<=m;i++){read(b[i]);}
    	a[0]=b[0]=-inf;
    	for(ri i=1;i<=n;i++){
    		for(ri j=1;j<=m;j++){
    			if(a[i]==b[j]){
    				for(ri k=0;k<j;k++){
    					if(b[k]<a[i]){
    						//f[i][j]=max(f[i][j],f[i-1][k]+1);
    						if(f[i][j]<f[i-1][k]+1){
    							f[i][j]=f[i-1][k]+1;
    							len[j]=len[k]+1;
    							for(ri p=1;p<=len[k];p++)path[j][p]=path[k][p];
    						}
    					}
    				}
    			}
    			else f[i][j]=f[i-1][j];
    			//ans=max(ans,f[i][j]);
    			path[j][len[j]]=b[j];
    			if(ans<f[i][j]){
    				ans=f[i][j];
    				ed=j;
    			}
    		}
    	}
    	printf("%d
    ",ans);
    	print(ed);	
    	return 0;
    }
    

    方法二

    我们考虑递推时的决策集合,(f[i][j])都是由(f[i][k](b[k]<a[i]))递推得到,那么我们如果在从(f[i][0])递推到(f[i][j])时我们已经记录下所有(f[i][k])的最大值设为(val),直接将(f[i][j])设为(max(f[i][j],val+1))就好了,打印路径的方法跟方法一类似

    这样时间复杂度能少个(N)

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <queue>
    #include <algorithm>
    #define ll long long 
    #define ri register int 
    #define ull unsigned long long 
    using std::min;
    using std::max;
    using std::swap;
    template <class T>inline void read(T &x){
    	x=0;int ne=0;char c;
    	while(!isdigit(c=getchar()))ne=c=='-';
    	x=c-48;
    	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    	x=ne?-x:x;return ;
    }
    const int maxn=505;
    const int inf=0x7ffffff;
    int n,m,a[maxn],b[maxn],f[maxn][maxn],path[maxn][maxn],len[maxn],ed;
    int main(){
    	read(n);
    	for(ri i=1;i<=n;i++){
    		read(a[i]);
    	}
    	read(m);
    	for(ri i=1;i<=m;i++){
    		read(b[i]);
    	}
    	int ans=-inf,val,lst=0;
    	for(ri i=1;i<=n;i++){
    		lst=0;
    		val=f[i-1][0];
    		for(ri j=1;j<=m;j++){
    		   if(a[i]==b[j]){
    		   	  if(val+1>f[i][j]){
    		   	  	 f[i][j]=val+1;
    		   	  	 for(ri k=1;k<=len[lst];k++)path[j][k]=path[lst][k];
    		   	  	 len[j]=len[lst]+1;	   	  	 
    			  }
    		   }
    		   else f[i][j]=f[i-1][j];
    		   path[j][len[j]]=b[j];
    		   //ans=max(ans,f[i][j]);
    		   if(f[i][j]>ans){
    		   	ans=f[i][j];
    		   	ed=j;
    		   }
    		   if(b[j]<a[i]){
    		   		//val=max(val,f[i-1][j]);
    		   		if(val<f[i-1][j]){
    		   			val=f[i-1][j];
    		   			lst=j;
    				}
    		   }
    		}
    	}	
    	printf("%d
    ",ans);
    	//printf("%d %d
    ",ed,len[ed]);
    	for(ri i=1;i<=len[ed];i++)printf("%d ",path[ed][i]);
    	return 0;
    }
    

    当然题解中还有(O(1))记录路径的方法,以及(O(N))的空间复杂度方法,这里先挖个坑吧

  • 相关阅读:
    Java_Activiti5_菜鸟也来学Activiti5工作流_之入门简单例子(一)
    Java_Activiti5_菜鸟也来学Activiti5工作流_之初识BPMN2.0的简单结构(五)
    Java_Activiti5_菜鸟也来学Activiti5工作流_之JUnit单元测试(四)
    Java_Activiti5_菜鸟也来学Activiti5工作流_之与Spring集成(三)
    Java_Activiti5_菜鸟也来学Activiti5工作流_之初识常用服务类和数据表(二)
    Html+Css+Js_之table每隔3行显示不同的两种颜色
    Java使用poi对Execl简单操作_总结
    Java使用poi对Execl简单_写_操作
    Java使用poi对Execl简单_读_操作
    Java使用poi对Execl简单_读和写_操作
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9579397.html
Copyright © 2011-2022 走看看