题目链接:

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\n",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\n",ans);
//printf("%d %d\n",ed,len[ed]);
for(ri i=1;i<=len[ed];i++)printf("%d ",path[ed][i]);
return 0;
}

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

CF10D-LCIS题解--线性DP+打印方案的更多相关文章

  1. CF10D LCIS(线性DP)

    题意:\(LCIS\)输出方案 变迁の时刻,标记它 P.S:特判没\(LCIS\)的情况 //#include <iostream> #include <cstdio> #in ...

  2. HDU2929 Bigger is Better[DP 打印方案 !]

    Bigger is Better Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  3. BestCoder Round #87 1002 Square Distance[DP 打印方案]

    Square Distance  Accepts: 73  Submissions: 598  Time Limit: 4000/2000 MS (Java/Others)  Memory Limit ...

  4. CH5101 LCIS【线性dp】

    5101 LCIS 0x50「动态规划」例题 描述 熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目.小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了 ...

  5. HDU 2296 Ring [AC自动机 DP 打印方案]

    Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissio ...

  6. 【题解】POJ1934 Trip (DP+记录方案)

    [题解]POJ1934 Trip (DP+记录方案) 题意: 传送门 刚开始我是这么设状态的(谁叫我DP没学好) \(dp(i,j)\)表示钦定选择\(i\)和\(j\)的LCS,然而你会发现这样钦定 ...

  7. 线性DP总结(LIS,LCS,LCIS,最长子段和)

    做了一段时间的线性dp的题目是时候做一个总结 线性动态规划无非就是在一个数组上搞嘛, 首先看一个最简单的问题: 一,最长字段和 下面为状态转移方程 for(int i=2;i<=n;i++) { ...

  8. Codeforces 176B (线性DP+字符串)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成 ...

  9. 线性dp

    线性dp应该是dp中比较简单的一类,不过也有难的.(矩乘优化递推请出门右转) 线性dp一般是用前面的状态去推后面的,也有用后面往前面推的,这时候把循环顺序倒一倒就行了.如果有的题又要从前往后推又要从后 ...

随机推荐

  1. ADB命令指令控制Android系统的WIFI连接开启/关闭状态

    Android系统的usb调试已开启,连接电脑(有ADB环境) 1.在cmd中,进入shell指令模式 adb shell 2.进入ROOT指令模式 su 3. 打开WIFI指令 svc wifi e ...

  2. Python datetime库计算两个时间点之间的分钟(秒、天)数

    计算两个时间点之间的分钟数 import datetime def minNums(startTime, endTime): '''计算两个时间点之间的分钟数''' # 处理格式,加上秒位 start ...

  3. mac安装phpmysql

    1.百度搜“phpmadmin”,还是一样,第二个因为是PC版本,不能用,点击第一个连接,去phpmyadmin的官网. 2.下载完毕后,进入到下载文件保存目录,双击压缩包,压缩包则会自动解压. 3. ...

  4. vs2017中信号与槽连接

    在vs2012里和在Qt Creator里添加信号和槽不一样,这里把两种环境下怎么添加详细说明一下 1.在vs2012里添加信号和槽 新建一个qt的项目QtDemo 在qtdeom.h里添加槽 pri ...

  5. 查看MySQL 连接信息--连接空闲时间及正在执行的SQL

    MySQL 客户端与MySQL server建立连接后,就可以执行SQL语句了. 如何查看一个连接上是否正在执行SQL语句,或者连接是否处于空闲呢? 下面我们做下测试. 1.查看连接的空闲时间 首先看 ...

  6. SOA相关资料

    http://www.cnblogs.com/mushroom/p/4369032.html

  7. Java对象和集合的拷贝/克隆/复制

    昨天同事遇到了一个奇怪的问题,他需要将一个JavaBean拷贝一份,然后对新创建的Bean进行操作.但是他对新的Bean操作后,会影响旧的Bean的值.当听到这个问题的时候,我第一反应就是他的拷贝方法 ...

  8. 横向对比分析Python解析XML的四种方式

    横向对比分析Python解析XML的四种方式 在最初学习PYTHON的时候,只知道有DOM和SAX两种解析方法,但是其效率都不够理想,由于需要处理的文件数量太大,这两种方式耗时太高无法接受. 在网络搜 ...

  9. Java之属性和普通方法

    一.定义类 上一节讲了很多深奥的理论,那么这节我们就得实践一下,先简单描述一下我们的实体世界:有一个学生小明,那么这个学生就是一个对象,这个对象有哪些属性和方法呢,我们可以先简单抽象一下,属性有(姓名 ...

  10. C语言递归之对称二叉树

    题目描述 给定一个二叉树,检查它是否是镜像对称的. 示例 二叉树 [1,2,2,3,4,4,3] 是对称的. / \ / \ / \ [1,2,2,null,3,null,3] 则不是镜像对称的. / ...