最长上升(不下降)子序列(LIS) 不同求解方法(动规、贪心)
给定一个序列,求出它的最长上升子序列或者是最长不下降子序列的长度 或者输出这个子序列
一、动态规划 O(n^2)
1.求长度
首先来讨论最长上升子序列的情况,即子序列是严格上升的
假如我们以dp[i]表示以a[i]为结尾的上升子序列的长度 那么对于 j (1<=j<i),如果a[j]<a[i],很显然:
代码:
#include <bits/stdc++.h> using namespace std; int anss=,i,n,j,a[],dp[]; int main()
{
cin>>n;
for(i=;i<n;i++)
{
cin>>a[i];
}
for(i=;i<n;i++)
{
dp[i]=;
for(j=;j<i;j++)
{
if(a[j]<a[i]) //如果是最长不下降子序列就改为 if(a[j]<=a[i])
{
dp[i]=max(dp[j]+,dp[i]);
}
}
if(dp[i]>anss)
anss=dp[i];
}
cout<<anss<<endl;
}
2.求序列
只需要从dp数组向前遍历,找到dp[i]==anss的之后再找dp[i]==anss-1的....以此类推即可
#include <bits/stdc++.h> using namespace std; int anss=,i,n,j,a[],dp[]; int main()
{
cin>>n;
for(i=;i<n;i++)
{
cin>>a[i];
}
for(i=;i<n;i++)
{
dp[i]=;
for(j=;j<i;j++)
{
if(a[j]<a[i])
{
dp[i]=max(dp[j]+,dp[i]);
}
}
if(dp[i]>anss)
anss=dp[i];
}
cout<<anss<<endl;
}
不过通常最长上升子序列的解是不唯一的,长度是唯一的。
二、贪心 O(nlogn)
对于一个上升子序列,显然其结尾元素越小,越有利于在后面接其他的元素,也就越可能变得更长。
因此,我们只需要维护 dp 数组(虽然已经不是动态规划了),对于每一个a [ i ],如果a [ i ]能接到 LIS 后面,就接上去;否则,就用 a [ i ] 取更新 dp数组:在dp数组中找到第一个大于等于a [ i ]的元素dp[ j ],用a [ i ]去更新dp [ j ]。怎么找到第一个大于等于的元素呢?只需要使用lower_bound()函数即可。
至于最长不下降子序列,只需要将 “在dp数组中找到第一个大于等于a [ i ]的元素dp[ j ]” 这一步改为找到第一个大于的元素即可。同样的将lower_bound换成upper_bound()
1.代码
#include <bits/stdc++.h> using namespace std; int anss=,i,n,j,a[],dp[],temp; int main()
{
cin>>n;
for(i=;i<n;i++)
{
cin>>a[i];
dp[i]=0x7ffffff;
}
for(i=;i<n;i++)
{
temp=lower_bound(dp,dp+n,a[i])-dp;
if(temp+>anss)
{
anss++;
}
dp[temp]=a[i];
}
cout<<anss<<endl;
}
2.求序列
只需要另外开一个数组b,记录dp[i]的位置,然后从b数组向前遍历,找到b[i]==anss的之后再找b[i]==anss-1的....以此类推
#include <bits/stdc++.h> using namespace std; int anss=,i,n,j,a[],dp[],temp,b[],c[]; int main()
{
cin>>n;
for(i=;i<n;i++)
{
cin>>a[i];
dp[i]=0x7ffffff;
}
for(i=;i<n;i++)
{
temp=lower_bound(dp,dp+n,a[i])-dp;
if(temp+>anss)
{
anss++;
}
dp[temp]=a[i];
b[i]=temp;
}
cout<<anss<<endl;
temp=anss-;
for(i=n-;i>=;i--)
{
if(b[i]==temp)
{
c[temp]=a[i];
temp--;
}
}
for(i=;i<anss;i++)
{
cout<<c[i]<<' ';
}
}
最长上升(不下降)子序列(LIS) 不同求解方法(动规、贪心)的更多相关文章
- 最长非降/下降子序列问题(DP)(待续...)
注意:抽象成以下描述即为最长非降/下降子序列问题(一维状态) 问题描述:在一个无序的序列a1,a2,a3,a4…an里,找到一个最长的序列满足:(不要求连续) ai<=aj<=ak…< ...
- Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列)
Luogu 1020 导弹拦截(动态规划,最长不下降子序列,二分,STL运用,贪心,单调队列) Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺 ...
- SPOJ 3943 - Nested Dolls 最长不下降子序列LIS(二分写法)
现在n(<=20000)个俄罗斯套娃,每个都有宽度wi和高度hi(均小于10000),要求w1<w2并且h1<h2的时候才可以合并,问最少能剩几个. [LIS]乍一看跟[这题]类似, ...
- HDU 1087 最长不下降子序列 LIS DP
Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. May ...
- hdu 4604 Deque(最长上升与下降子序列-能够重复)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4604 这个题解有点问题,暂时没时间改,还是参考别人的吧 #include <cstdio> ...
- 求最长非降(递增)子序列LIS的长度,及注意事项
非降序列(Increasing Sequence)例如: (1) 完全递增型序列:S={1,3,6,7,9} (2) 部分存在等于的序列:S={1,3,3,6,9} S的非降子序列:由原序列S的元素组 ...
- Longest Ordered Subsequence POJ - 2533 dp 最长上升/不下降 子序列
#include<iostream> using namespace std ; ; int f[N]; int a[N]; int n; int main() { cin>> ...
- 动态规划——最长不下降子序列(LIS)
最长不降子序列是这样一个问题: 下面介绍动态规划的做法. 令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度.这样对 A[i] 来说就会有两种可能: 如果存在 A[i] 之前的元素 A[j] ...
- HDU 6357.Hills And Valleys-字符串非严格递增子序列(LIS最长非下降子序列)+动态规划(区间翻转l,r找最长非递减子序列),好题哇 (2018 Multi-University Training Contest 5 1008)
6357. Hills And Valleys 自己感觉这是个好题,应该是经典题目,所以半路选手补了这道字符串的动态规划题目. 题意就是给你一个串,翻转任意区间一次,求最长的非下降子序列. 一看题面写 ...
随机推荐
- redis string类型设置过期时间后 再进行set操作,会清除过期时间
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qq_41756437/article/d ...
- CSS的五种基本选择器
要使用css对HTML页面中的元素实现一对一,一对多或者多对一的控制,这就需要用到CSS选择器. ㈠什么是选择器? 每一条css样式定义由两部分组成,形式如下: [code] 选择器{样式} [/co ...
- docker部署war+tomcat8
注意:本文只是将jenkins.war作为一个war包来操作,实际上要使用jenkins还要同时安装git.maven等. 1.购买阿里云服务器(Ubuntu 18.04), 设置密码,root+pa ...
- python re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None:而re.search匹配整个字符串,直到找到一个匹配. #!/usr/bin/python impor ...
- Android的SQLite基本操作
涉及SQLite的增删改查,结果用log显示 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ...
- TCP连接数配置
一般的设置规则为: 系统最大文件数>可用端口>用户最大文件数 sysctl -a | grep file-max cat /proc/sys/fs/file-max 这表明这台Linux系 ...
- 对象转JSON字符串与json字符串转对象方法
JSON.stringify()[从一个对象中解析出字符串] JSON.parse()[从一个json字符串中解析出对象] var data = {"nums": 1, " ...
- Linux下运行scala语言的jar包
1.新建project 2.打包 3.linux下运行jar包 #First.jar为jar包名,Test为主类名 [root@FI-2 Desktop]# spark-submit First.ja ...
- scala基础-1
函数式编程 并行编程 多核计算.云计算 引用透明,给值确定,结果也确定 数据类型 三种变量修饰符 val 定义immutable variable var 定义mutable va ...
- Div内容居中
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...