题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1134

这里说下,最长上升子序列和最长不降子序列几乎一样,只是判断=的时候注意一下。另外最长不降子序列经常反过来考,有几个最长不降,而不是求它的长度。(经典例题导弹拦截系统)

分析和思路:

我们维护当前最长的长度len,用vis[j]存储长度为j的所有子序列中最小的末尾数值,那么对于当前数据a[i],如果数组vis中存在比其大的元素我们用a[i]替换掉vis中第一个比a[i]大的数,若不存在,那么我们将a[i]加入vis末尾,此时数组长度+1,如此我们便维护了数组vis的性质,最终得到的len就是答案了.因为数组vis再加入时就保持了递增的性质,所以在查找时可以用二分查找函数lower_bound把时间复杂度降到n*logn。

当然这题不用二分函数也可以过,其实我反而觉得不用函数更好(当然再不超时的前提下),自己一步一步的慢慢实现这个过程能极大的帮助理解这个方法(算法)的本质,体会到它的巧妙(当初仔细想了几遍,想通了巧妙之后发现它是如此有趣^^),过段时间后也不会轻易忘记 。

这个题是要求严格递增子序列(ps:这类题<=或<的地方要区分清楚理解清楚)

 1 #include <iostream>
 2 using namespace std;
 3 const int maxn=1e6+5;
 4 int a[maxn],vis[maxn];
 5 int main()
 6 {
 7       int n;
 8       cin>>n;
 9       for(int i=1;i<=n;i++) cin>>a[i];
10       for(int i=0;i<=n;i++) vis[i]=-1e9-1;
11
12       vis[1]=a[1];int len=1;
13       for(int i=2;i<=n;i++)
14       {
15           int f=0;
16           for(int j=1;j<=len;j++)//<len就行不是i(len即为该递增子序列)
17           {
18               if(a[i]<=vis[j])//区别就在这,有=,把相等的算进来如此就在递增序列中舍弃了(严格最长递增子序列,如1,2,3,4)
19               {                 //如果是a[i]<vis[j],就把相等的算在递增序列中了(非严格最长递增子序列,如1,2,2,2)
20                   f=1;
21                   vis[j]=a[i];
22                   break;
23               }
24           }
25           if(!f) vis[++len]=a[i];//递增序列中都比a[i]<=,所以序列长度可+1
26       }
27       cout<<len<<endl;
28
29       return 0;
30 } 

还有一道极类似题,hdu最少拦截系统,http://acm.hdu.edu.cn/showproblem.php?pid=1257

分析和思路:

其实就是把lis反过来理解,代码都不用变!只不过这个思维转换的过程不好想,我也是看了别人说的之后才转换过来想通。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 const int maxn=1e6+5;
 6 int a[maxn],b[maxn],vis[maxn];
 7 int main()
 8 {
 9     ios::sync_with_stdio(false);cin.tie(0);
10
11     int n;
12     while(cin>>n)
13     {
14          for(int i=1;i<=n;i++) cin>>a[i];
15          for(int i=0;i<=n;i++) vis[i]=-1e9-1;
16
17          vis[1]=a[1];int len=1;
18          for(int i=2;i<=n;i++)
19          {
20              int f=0;
21              for(int j=1;j<=len;j++)
22              {                      //=重要!把相等时(不用再开一套系统)也要装进去(代表非严格递降,即不高于)
23                  if(a[i]<=vis[j])//如果<,则是严格递降,是高于
24                  {                  //与lis意义不同,高度降低代表当前这套的最大高度
25                      f=1;
26                      vis[j]=a[i];
27                      break;
28                  }
29              }
30              if(!f) vis[++len]=a[i];//与lis意义不同,代表增加一套系统(lis是存的那一条最长递增列)
31          }
32          cout<<len<<endl;
33          memset(vis,0,sizeof(vis));
34     }
35
36     return 0;
37 } 

洛谷上述两个,https://www.luogu.org/problemnew/show/P1020

反着正着都考了,同时更新为二分查找做法

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <vector>
 5 #include <algorithm>
 6 #define sc(x) scanf("%d",&x)
 7 #define pr(x) printf("%d",x)
 8 #define ppp putchar('\n')
 9 using namespace std;
10 const int maxn=1e6+5;
11 int a[maxn],vis[maxn],viss[maxn];
12 int main()
13 {
14     int n=1;
15     while(sc(a[n])!=EOF) n++;
16     n--;
17     for(int i=0;i<=n;i++) vis[i]=-1e9-1;
18
19     int len1=1;
20     vis[1]=a[1];
21     for(int i=2;i<=n;i++)
22     {
23         /*for(int j=1;j<=len1;j++)
24         {
25             if(a[i]<=vis[j])
26             {
27                 f1=1;
28                 vis[j]=a[i];
29                 break;
30             }
31         }*/
32
33         int f1=lower_bound(vis+1,vis+1+len1,a[i])-(vis+1)+1;
34         if(f1<=len1) vis[f1]=a[i];
35         else vis[++len1]=a[i];
36     }
37
38     reverse(a+1,a+1+n);
39     int len2=1;
40     viss[1]=a[1];
41     for(int i=2;i<=n;i++)
42     {
43         /*for(int j=1;j<=len2;j++)
44         {
45             if(a[i]<viss[j])
46             {
47                 f2=1;
48                 viss[j]=a[i];
49                 break;
50             }
51         }*/
52         int f2=upper_bound(viss+1,viss+1+len2,a[i])-(viss+1)+1;
53         if(f2<=len2) viss[f2]=a[i];
54         else viss[++len2]=a[i];
55     }
56     pr(len2);ppp;
57     pr(len1);ppp;
58
59     memset(vis,0,sizeof(vis));
60     memset(viss,0,sizeof(viss));
61
62     return 0;
63 }

转载于:https://www.cnblogs.com/redblackk/p/9533435.html

51nod1134最长递增子序列(dp)相关推荐

  1. 51Nod-1134 最长递增子序列【LIS】

    1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如 ...

  2. 最长单调递增子序列_最长递增子序列(动态规划 + 二分搜索)

    题目 给定数组arr,返回arr的最长递增子序列 举例:arr = [2,1,5,3,6,4,8,9,7],返回的最长递增子序列为[1,3,4,8,9] 要求:如果arr的长度为N,请实现时间复杂度为 ...

  3. 代码随想录训练营day52, 最长递增子序列, 最长连续递增序列, 最长重复子数组

    最长递增子序列 dp[i]的定义, 表示i之前包括i的以nums[i]结尾最长上升子序列的长度 递推: if(nums[i] > nums[j]) dp[i] = max(dp[i], dp[j ...

  4. LeetCode 673. 最长递增子序列的个数(DP)

    1. 题目 给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, ...

  5. 【动态规划刷题笔记】线性dp:合唱队形(最长递增子序列的变体)

    [NOIP2004 提高组] 合唱队形 - 洛谷 思路:最少出列,即挑出最多,即找最长递增子序列和最长递减子序列 设dp1[i]为以h[i]结尾的最长递增子序列 dp2[i]为以h[i]开头的最长递减 ...

  6. 最长递增子序列的两种解法

    以LeetCode-300为例: O(n^2)解法: dp数组表示以i结尾的最长递增子序列的长度 class Solution { public:int lengthOfLIS(vector<i ...

  7. 洛谷P2766-最长递增子序列问题

    chunlvxiong的博客 题目描述: 给定正整数序列x1,...,xn (1≤n≤500). 1.计算其最长递增子序列的长度s. 2.计算从给定的序列中最多可取出多少个长度为s的递增子序列. 3. ...

  8. 动态规划(最长递增子序列)---最长递增子序列

    最长递增子序列 300. Longest Increasing Subsequence (Medium) 题目描述:   给定一个数组,找到它的最长递增子序列 思路分析:   动态规划思想,定义一个数 ...

  9. 112. Leetcode 673. 最长递增子序列的个数 (动态规划-子序列问题)

    步骤一.确定状态: 确定dp数组及下标含义 dp[i]表示以nums[i]结尾的数组最长递增子序列的长度, count数组, count[i]记 录以nums[i]结尾的数组,最长递增子序列的个数. ...

最新文章

  1. 【SVN】svn“E155017工作副本的参考文件损坏、E200014文件校验和不匹配”的解决方法
  2. 如何添加媒体控件Windows Media Player到工具箱中
  3. 模块和包——Python
  4. json读取json文件,上传到后台
  5. date 日期时间命令
  6. SENSOR DVP接口介绍
  7. 高效的国产CAD设计工具,云端三维CAD设计平台:CrownCAD
  8. 腾讯云大学大咖分享 | 自然语言处理技术(NLP)究竟能做些什么?
  9. Db2插入数据溢出报错测试
  10. 试戴耳钉会感染艾滋病吗?
  11. Android 10.0热点为Enhanced Open模式时不允许WiFI和热点同时开启代码流程梳理
  12. Maven打包常见问题
  13. Android项目源码分享
  14. 移植tslib后,运行报错 Couldnt load module linear
  15. Web前端开发工资差距是如何产生的?根源是技术水平
  16. 高数_向量代数_单位向量_向量与坐标轴的夹角
  17. VIC水文模型入门攻略(下) 汇流和其他相关
  18. spring 自定义标签 学习
  19. 华为 组播之IGMPv1
  20. c语言计算时间差的程序小时和分钟,C语言输入两个时间(同一天的两个时和分),计算其时间差,输出相差几小时几分钟?...

热门文章

  1. 在InternetExplorer.Application中显示本地图片
  2. AFN的简单二次封装
  3. WINDOWS访问虚拟机RedHat搭配的Apache2服务器
  4. 在android中如何使用UDP和TCP传输
  5. 11.29 广州国际设计周
  6. [BZOJ1026]windy数
  7. jQuery插件编写基础之“又见弹窗”
  8. IIS7 配置 PHP
  9. 漫画:混乱的标记语言XHTML2/HTML5
  10. C#网络版斗地主——出牌权限的传递