codevs 1576 最长严格上升子序列

题目链接:http://codevs.cn/problem/1576/
题目描述 Description

给一个数组a1, a2 ... an,找到最长的上升降子序列ab1<ab2< .. <abk,其中b1<b2<..bk。

输出长度即可。

输入描述 Input Description

第一行,一个整数N。

第二行 ,N个整数(N < = 5000)

输出描述 Output Description

输出K的极大值,即最长不下降子序列的长度

样例输入 Sample Input

5

9 3 6 2 7

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

【样例解释】

最长不下降子序列为3,6,7

解题思路

参考:北大郭炜老师

1.找子问题:“求以ak( k=1, 2, 3…N)为终点的最长上升子序列的长度”
一个上升子序列中最右边的那个数,称为该子序列的“终点”。
虽然这个子问题和原问题形式上并不完全一样,但是只要这N个子问题都解决了,那么这N个子问题的解中,最大的那个就是整个问题的解。

2. 确定状态
子问题只和一个变量-- 数字的位置相关。因此序列中数的位置k 就是“状态”,而状态 k 对应的“值”,就是以a[k]做为“终点”的最长上升子序列的长度。状态一共有N个。

3. 找出状态转移方程

maxLen [k]表示以a[k]做为“终点”的最长上升子序列的长度那么:
初始状态: maxLen [1] = 1
maxLen[k]= max { maxLen [i]: 1<=i < k 且 a[i ]< a[k]且 k≠1 } + 1
若找不到这样的i,则maxLen[k] = 1

maxLen[k]的值,就是在a[k]左边,“终点”数值小于a[k] ,且长度最大的那个上升子序列的长度再加1。因为a[k]左边任何“终点”小于a[k]的子序列,加上a[k]后就能形成一个更长的上升子序列 。

 1 #include <stdio.h>
 2 #define maxN 5005
 3 int n,a[maxN],maxLen[maxN];//maxLen[k]表示以a[k]做为“终点”的最长上升子序列的长度
 4 int main(int argc, char *argv[])
 5 {
 6     int i,j;
 7     scanf("%d",&n);
 8     for(i=0;i<n;i++) {  scanf("%d",&a[i]); maxLen[i]=1;  }
 9     
10     for(i=1;i<n;i++)//枚举所有子序列的终点 
11     {
12         for(j=0;j<i;j++)//枚举以a[i]做终点的子序列中a[i]的前缀元素 
13         {
14             if(a[j]<a[i])//尝试用a[j]做a[i]的直接前缀形成新的子序列 
15             {
16                 maxLen[i]=(maxLen[j]+1>maxLen[i]?maxLen[j]+1:maxLen[i]);
17             }
18         }
19     }
20     printf("%d\n",maxLen[n-1]);
21     return 0;
22 }

上面的代码写错了,抱歉。更正如下:

 1 #include <stdio.h>
 2 #define maxN 5005
 3 int main(int argc, char *argv[])
 4 {
 5     int i,j,t;
 6     int n,a[maxN],maxLen[maxN];//maxLen[k]表示以a[k]做为“终点”的最长上升子序列的长度
 7     int max;
 8     
 9     scanf("%d",&n);
10     for(i=0;i<n;i++) {  scanf("%d",&a[i]); maxLen[i]=1;  }
11     for(i=1;i<n;i++)//枚举所有子序列的终点 
12     {
13         for(j=0;j<i;j++)//枚举以a[i]做终点的子序列中a[i]的前缀元素 
14         {
15             if(a[j]<a[i])//尝试用a[j]做a[i]的直接前缀形成新的子序列 
16             {
17                 maxLen[i]=(maxLen[j]+1>maxLen[i]?maxLen[j]+1:maxLen[i]);
18             }
19         }
20     }
21     max=maxLen[0];
22     for(i=1;i<n;i++)
23         if(maxLen[i]>max) max=maxLen[i];
24     printf("%d\n",max);
25     return 0;
26 }

 

思考题 : 如何改进程序,使之能够输出最长上升子序列 ?

思路:新增pre[ ],其中pre[k]=x表示在a[ ]序列构成的若干个上升子序列中,a[k]的前驱是a[x]。一开始pre[ ]全部初始化为-1表示一开始所有元素的前驱都是自己本身。在循环求解maxLen[i]的同时,更新pre[i]。最后在扫描出maxLen[ ]最大值为maxLen[i]以后,从pre[i]往前推即可。假如要顺序输出该最长上升子序列,可以把逆推pre[ ]的过程保存再输出。

参考代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define maxN 5005
 4 int main(int argc, char *argv[])
 5 {
 6     int i,j,t;
 7     int n,a[maxN],maxLen[maxN];//maxLen[k]表示以a[k]做为“终点”的最长上升子序列的长度
 8     int max;
 9     int pre[maxN];
10     int c[maxN],maxIndex;
11     
12     memset(pre,-1,sizeof(pre));
13     
14     scanf("%d",&n);
15     for(i=0;i<n;i++) {  scanf("%d",&a[i]); maxLen[i]=1;  }
16     
17     for(i=1;i<n;i++)//枚举所有子序列的终点 
18     {
19         for(j=0;j<i;j++)//枚举以a[i]做终点的子序列中a[i]的前缀元素 
20         {
21             if(a[j]<a[i])//尝试用a[j]做a[i]的直接前缀形成新的子序列 
22             {
23                 if(maxLen[j]+1>maxLen[i])
24                 {
25                     maxLen[i]=maxLen[j]+1;
26                     pre[i]=j;
27                 }
28             }
29         }
30     }
31     max=maxLen[0];
32     for(i=1;i<n;i++)
33         if(maxLen[i]>max) { max=maxLen[i]; maxIndex=i; }
34     printf("%d\n",max);
35     
36     j=0;
37     c[j++]=a[maxIndex];
38     while(pre[maxIndex]!=-1)
39     {
40         maxIndex=pre[maxIndex];
41         c[j++]=a[maxIndex];
42     }
43     for(i=j-1;i>=0;i--)
44     {
45         printf("%d ",c[i]);
46     }
47     printf("\n");
48     return 0;
49 }
View Code

 

 

输出最长上升子序列的另一种思路:

 1 #include <stdio.h>
 2 int n,size,a[1005][5],s,ans,next;
 3 int main(int argc, char *argv[])
 4 {
 5     scanf("%d",&n);
 6     for(int i=0;i<n;i++)
 7     {
 8         int t;
 9         scanf("%d",&t);
10         a[i][0]=t;a[i][1]=1;a[i][2]=0;
11         //a[i][1]表示以a[i][0]开头的最长上升子序列的长度。
12         //a[i][2]表示在以a[i][0]开头的最长上升子序列中a[i][0]的下一个数在原序列中的下标。
13     }
14     
15     for(int i=n-2;i>=0;i--)
16     {
17         size=next=0;
18         for(int j=i+1;j<n;j++)
19             if(a[j][0]>a[i][0]&&a[j][1]>size) {size=a[j][1];next=j;}
20         if(size>0) {a[i][1]=size+1;a[i][2]=next;}
21     }
22     
23     ans=0;
24     for(int i=0;i<n;i++)
25         if(a[i][1]>a[ans][1]) ans=i;
26         
27     printf("%d\n",a[ans][1]);
28     
29     /*for(int i=0;i<n;i++)
30         printf("%d %d %d %d\n",a[i][0],a[i][1],a[i][2],i);*/
31     
32     int i=ans;
33     while(a[i][2]>0)
34     {
35         printf("%d ",a[i][0]);
36         i=a[i][2];
37     }
38     printf("%d\n",a[i][0]);
39     return 0;
40 }
View Code

 

测试OJ地址:

http://noi.openjudge.cn/ch0206/1759/

http://bailian.openjudge.cn/practice/2757/

 

转载于:https://www.cnblogs.com/huashanqingzhu/p/7326739.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/252142.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx服务器开启缓存、反向代理

一、反向代理配置 1、反向代理服务器配置如下 反向代理就是需要这一行proxy_pass来完成。当我们要访问后端web服务器的时候&#xff0c;我们只需要访问代理服务器就可以了&#xff0c;此时代理服务器就充当后端web服务器的角色。proxy_pass依赖的模块是&#xff1a; 至于后两行…

Halcon:区域特征:select_shape(Regions : SelectedRegions : Features, Operation, Min, Max : )

Region特征一览&#xff1a; 特征 英 译 备注 area Area of the object 对象的面积 row Row index of the center 中心点的行坐标 column Column index of the center 中心点的列坐标 width Width of the region 区域的宽度 height Height of the…

Web应用主动侦测工具Skipfish

Web应用主动侦测工具SkipfishSkipfish是Kali Linux附带的一个主动Web应用侦测工具。该工具会首先尽可能获取所有网站路径&#xff0c;进行访问&#xff0c;然后根据返回的内容&#xff0c;检测是否存在漏洞。该工具采用字典爆破和网页爬行两种方式获取网站。一旦获取网页内容&a…

7步让你get首个数据科学实习

由于数据科学的庞大和复杂&#xff0c;如果你没有相关的实习经历的话&#xff0c;成为数据科学家的道路将会更加艰巨和困难。即使是经验丰富的人&#xff0c;实习也是转型进入数据科学领域的一种有效方式。 那么&#xff0c;寻找数据科学实习有哪些技巧&#xff1f;本文总结了数…

Halcon:Image、region、xld常用的处理

一、读取文件夹中的所有图片 list_files (C:/Users/fuping.liu/Desktop/槟榔有无头/有头, [files,follow_links], ImageFiles) tuple_regexp_select (ImageFiles, [\(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$,ignore_case], ImageFiles)for Index :…

赛码网算法: 上台阶 ( python3实现 、c实现)

上台阶 题目描述 有一楼梯共m级&#xff0c;刚开始时你在第一级&#xff0c;若每次只能跨上一级或二级&#xff0c;要走上第m级&#xff0c;共有多少走法&#xff1f;注&#xff1a;规定从一级到一级有0种走法。 输入…

Halcon: 畸变矫正与标定(1)

1、 Halcon相机标定和图像矫正 对于相机采集的图片&#xff0c;会由于相机本身和透镜的影响产生形变&#xff0c;通常需要对相机进行标定&#xff0c;获取相机的内参或内外参&#xff0c;然后矫正其畸变。相机畸变主要分为径向畸变和切向畸变&#xff0c;其中径向畸变是由透…

conda install 出错

在下载包时出现下面的错误&#xff1a; userdeMBP:pytorch user$ conda install -n deeplearning matplotlib Solving environment: failedCondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://repo.anaconda.com/pkgs/main/osx-64/repodata.json.bz2> Elapsed…

算法入门经典 第三章

scanf 遇到tab或空格或换行符停下来1.例题2-1 7744问题 从数本身看 从个位数的数字看#include <iostream>#include<math.h>using namespace std; int main(){ for(int a1;a<9;a) { for(int b1;b<9;b) { int n1100*a11*b;//floor x 等于1的区间为[1,2),florr(…

Halcon :畸变矫正与标定(2)

相机标定1.相机标定是什么2.怎么使用halcon进行相机内外参标定&#xff1f; &#xff08;1&#xff09;搭建硬件1.**相机连好电脑&#xff0c;用相机厂家软件打开相机&#xff0c;检查一下相机是否正常。**2.**接下来使用halcon连接相机**&#xff08;2&#xff09;开始标定1.*…

jQuery2

一、层次选择器 1、后代选择器$("div p"):div中所有的p标签元素 2、自带选择器$("div>p")&#xff1a;div中的子代是p的第一层元素 3、兄弟选择器$("divp")和div是兄弟的p标签 4、相邻兄弟选择器$("div~p")与div相邻的p标签 二、jQ…

HTTP协议详解(转载)

http://www.cnblogs.com/TankXiao/archive/2012/02/13/2342672.html 转载于:https://www.cnblogs.com/youmei11/p/8608007.html

bzoj1016 [JSOI2008]最小生成树计数

1016: [JSOI2008]最小生成树计数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6032 Solved: 2452[Submit][Status][Discuss]Description 现在给出了一个简单无向加权图。你不满足于求出这个图的最小生成树&#xff0c;而希望知道这个图中有多少个不同的最小生成树。&…

http请求概述

当浏览器输入网址后 浏览器首先向DNS域名解析服务器发送请求。DNS反解析&#xff1a;根据浏览器请求地址中的域名&#xff0c;到DNS服务器中找到对应的服务器外网IP地址通过找到外网IP&#xff0c;向对应的服务器发请求&#xff08;首先访问服务器的WEB站点管理工具&#xff1a…

Halcon:二维仿射变换实例探究

二维仿射变换&#xff0c;顾名思义就是在二维平面内&#xff0c;对对象进行平移、旋转、缩放等变换的行为&#xff08;当然还有其他的变换&#xff0c;这里仅论述这三种最常见的&#xff09;。 Halcon中进行仿射变换的常见步骤如下&#xff1a; ① 通过hom_mat2d_identity算子…

剑指Offer-数组中重复的数字

题目描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的&#xff0c;但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如&#xff0c;如果输入长度为7的数组{2,3,1,0,2,5,3}&#xff0c;那么对应的…

CSS2--字体样式

## CSS2 字体样式 ##### font-family 字体族 - 规定元素的字体系列 - 把多个字体作为一个"回退"系统保存.保证浏览器的支持 - Microsoft YaHei, tahoma, arial, Hiragino Sans GB, sans-serif ##### font 字体类型 - 衬线字体(serif)&#xff1a;在字的笔划开始及结束…

虚拟机中访问连接在物理机上的摄像机(使用桥接)

最近在使用摄像机SDK做开发&#xff0c;开发好之后物理机上没有环境&#xff0c;所以弄了个虚拟机进行测试&#xff0c;就如何在虚拟机中连接摄像机做下记录。 步骤 &#xff11;.物理机上对虚拟机的适配器和摄像机的适配器设置为相同网段并进行桥接&#xff08;注意与摄像机网…

Halcon:手眼标定——眼在手外与眼在手上

为什么需要九点标定&#xff1f; 为了得到机械和相机的关系&#xff0c;就好比人的手和眼的关系。我们用手将一个物体放到空间的一个位置&#xff0c;用眼看到这个物体&#xff0c;这也存在两个坐标系&#xff0c;一个是手所在的运动空间的坐标系&#xff0c;一个是视网膜上成像…

grep 正则匹配

\{0,n\}&#xff1a;至多n次 \{\ 匹配/etc/passwd文件中数字出现只是数字1次到3次 匹配/etc/grub2.cfg文件以一个空格开头匹配一个字符的文件的所有行 显示以LISTEN结尾的行 显示匹配右边以LISTEN结尾匹配一个或者多个空格的所有输出 分组及引用&#xff1a;讲一个或者多个字符…