题目描述:

怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯。

而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的便于操作的滑翔翼。

有一天,怪盗基德像往常一样偷走了一颗珍贵的钻石,不料却被柯南小朋友识破了伪装,而他的滑翔翼的动力装置也被柯南踢出的足球破坏了。不得已,怪盗基德只能操作受损的滑翔翼逃脱。

假设城市中一共有N幢建筑排成一条线,每幢建筑的高度各不相同。

初始时,怪盗基德可以在任何一幢建筑的顶端。

他可以选择一个方向逃跑,但是不能中途改变方向(因为中森警部会在后面追击)。

因为滑翔翼动力装置受损,他只能往下滑行(即:只能从较高的建筑滑翔到较低的建筑)。

他希望尽可能多地经过不同建筑的顶部,这样可以减缓下降时的冲击力,减少受伤的可能性。

请问,他最多可以经过多少幢不同建筑的顶部(包含初始时的建筑)?

输入格式

输入数据第一行是一个整数K,代表有K组测试数据。

每组测试数据包含两行:第一行是一个整数N,代表有N幢建筑。第二行包含N个不同的整数,每一个对应一幢建筑的高度h,按照建筑的排列顺序给出。

输出格式

对于每一组测试数据,输出一行,包含一个整数,代表怪盗基德最多可以经过的建筑数量。

数据范围

1≤K≤100,
1≤N≤100,
0<h<10000

输入样例:

3
8
300 207 155 299 298 170 158 65
8
65 158 170 298 299 155 207 300
10
2 1 3 4 5 6 7 8 9 10

输出样例:

6
6
9

分析:

从本题起进入到最长上升子序列模型,LIS问题动态规划解法见AcWing 895 最长上升子序列,贪心+二分解法见AcWing 896 最长上升子序列 II。

本题题意是说一排建筑高低不同,怪盗基德可以选择其中任意一个建筑作为起点,朝一个方向向高度低的建筑物滑翔,求其能经过的建筑物的最大数量。而普通的LIS问题相当于在一排建筑中找一个建筑作为起点,然后向左滑翔的最大长度,也就是说,本题相当于对一个线性序列正向和逆向求最长下降子序列长度。可以注意到逆向的最长下降子序列相当于正向的最长上升子序列,正向的最长下降子序列相当于逆向的最长上升子序列,所以本题简化为一句话就是正向和逆向分别求LIS长度,找出二者中的较大值。

方法一:

使用动态规划求LIS,f[i]表示以a[i]为末字符的最长上升子序列长度,状态转移方程为f[i] = max(f[k]) + 1,k < i且a[k] < a[i]。求完f数组后,最后LIS的长度等于f数组中的最大者。从左往右遍历序列求得的LIS长度为len1,从右往左遍历求得的LIS长度为len2,本题要求的能够滑翔的最大长度为max(len1,len2)。

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 105;
int a[N],f[N];
int main(){int n,T;cin>>T;while(T--){cin>>n;for(int i = 1;i <= n;i++)   cin>>a[i];int res = 0;for(int i = 1;i <= n;i++){f[i] = 1;for(int j = 1;j < i;j++){if(a[j]<a[i])   f[i] = max(f[i],f[j]+1);}res = max(res,f[i]);}for(int i = n;i >= 1;i--){f[i] = 1;for(int j = n;j > i;j--){if(a[j]<a[i])   f[i] = max(f[i],f[j]+1);}res = max(res,f[i]);}cout<<res<<endl;}return 0;
}

方法二:

贪心+二分求解LIS。长度为len的上升子序列我们只需要保存其中末字符最小的那一串,也就是说,我们只需要找到长度为1,2,3,...的上升子序列的末字符是什么就可以延伸LIS的长度了。之前LIS问题中已经证明了,存放各个长度上升子序列末字符的数组是单调递增的。我们只需要构造出该数组,构造完成后该数组的长度就是LIS的长度。构造f数组的过程可以描述为:在遍历序列的过程中查找f数组中小于当前遍历元素a[i]的最大元素的位置,并将a[i]放到该位置的后一个位置即可。

二分就是要在f数组中找到小于a[i]的最大数的位置l,所以f[mid] < a[i]时,l = mid;否则r = mid - 1,这是为了最终二分终止时l == r,即r的最终位置等于l,都是处于小于a[i]的位置,所以当f[mid] >= a[i]时,r应该等于mid - 1。注意r恰好比l大1时,如果mid = l + r >> 1,则mid = l,若此时f[l] < a[i],则l = mid = l,会导致l与r始终无法重合,故mid设置为l + r + 1 >> 1,即(l + r) / 2的上取整,mid的值等于r时,r总会减小,所以循环必会终止。下面二分代码还有个巧妙的地方在于len = 0时,l == r,此时f[l + 1] = f[1] = a[1],即跳过了f[0]直接为f数组中上升子序列长度为1的末字符赋值。

#include<iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=105;
int a[N],f[N];
int main(){int n,T;cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];int l,r,len=0,res = 0;for(int i = 1;i <= n;i++){l = 0,r = len;while(l < r){int mid = l + r  + 1>> 1;if(f[mid] < a[i])   l = mid;else    r = mid - 1;} len = max(len,l + 1);f[l + 1] = a[i];}res = len,len = 0;for(int i=n;i>=1;i--){l = 0,r = len;while(l < r){int mid = l + r  + 1>> 1;if(f[mid] < a[i])   l = mid;else    r = mid - 1;} len = max(len,l + 1);f[l + 1] = a[i];}res = max(res,len);cout<<res<<endl;}
}

AcWing 1017 怪盗基德的滑翔翼相关推荐

  1. AcWing 1017. 怪盗基德的滑翔翼

    怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯. 而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的便于操作的滑翔翼. 有一天,怪盗基德像往 ...

  2. 1286:怪盗基德的滑翔翼(错)

    /* 1286:怪盗基德的滑翔翼(错) http://ybt.ssoier.cn:8088/problem_show.php?pid=1286 请找出此程序的问题  */ #include<bi ...

  3. 1286:怪盗基德的滑翔翼-2019-07-03(《信息学奥赛一本通》)

    /* 1286:怪盗基德的滑翔翼-2019-07-03(支扬帆) http://ybt.ssoier.cn:8088/problem_show.php?pid=1286 */ #include < ...

  4. C++动态规划算法之怪盗基德的滑翔翼

    怪盗基德的滑翔翼 Description 怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯.而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的 ...

  5. 2017北大信科夏令营机试E:怪盗基德的滑翔翼

    E:怪盗基德的滑翔翼 查看 提交 统计 提问 总时间限制:  1000ms  内存限制:  65536kB 描述 怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯.而他最为突出的地方,就 ...

  6. 小码王(洛谷)怪盗基德的滑翔翼

    [DP]怪盗基德的滑翔翼 题目背景 怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯.而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的便于操 ...

  7. 怪盗基德的滑翔翼(信息学奥赛一本通-T286)

    [题目描述] 怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯.而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的便于操作的滑翔翼. 有一天, ...

  8. AcWing1017.怪盗基德的滑翔翼

    题目描述 怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯. 而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的便于操作的滑翔翼. 有一天,怪 ...

  9. 怪盗基德的滑翔翼 线性DP 最长上升子序列

最新文章

  1. Oracle使用手册(三)---存储过程与触发器
  2. 2张图片就能「算出」一段视频,Reddit网友都惊呆了 | 旷视北大出品
  3. python小程序-第一个python小程序——即时动态时钟(代码解读)
  4. delphi 执行一个外部程序,当外部程序结束后言主程序立即响应
  5. hdu_1233(最小生成树)
  6. php堆是什么,PHP 堆与堆排序的详解
  7. python连接redis哨兵_python连接redis sentinel集群
  8. 一次kvm嵌套虚拟化踩坑经历
  9. js 单精度浮点数转10进制_确保前端 JavaScript 浮点数精度的四则运算方法
  10. Project Euler Problem 25 1000-digit Fibonacci number
  11. 11.PHP memcache 与 memcached 区别
  12. c++ 实现一个object类_一个Java类就能实现微服务架构的权限认证
  13. pythoncss50使用教程_Python学习(二十) —— 前端之CSS
  14. Python报错unindent does not match any outer indentation level如何解决?
  15. ssm+微信小程序基于小程序的医院预约挂号系统毕业设计源码260839
  16. NYOJ54 小明的存钱计划
  17. java mysql 端口_如何在JAVA中建立MySQL连接?在locahost上设置的端口号是多少?
  18. sci四区大水刊 计算机,sci四区大水刊_sci四区免费大水刊_sci四区什么水平
  19. Excel日期显示为数字,不能正常显示为日期
  20. WordPress文章标题显示汉字方法

热门文章

  1. GlusterFS 之 POSIX ACLs
  2. 如何使用ARM协处理器CP15在32位ARRCH模式下操作64位寄存器)
  3. MikTex + VS Code 配置教程
  4. Chrome打包扩展程序错误,清单文件缺失或不可读
  5. Python地理位置信息库geopy的使用(一):基本使用
  6. java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSource解决方法
  7. printThis前端打印插件
  8. 提升思维品质,不可不知的5个工具
  9. tps协议和onvif协议_onvif协议是什么
  10. 每周一品 · 无线充电设备中的磁性材料