导弹拦截之测试版
1000(ms)
10000(kb)
1166 / 3025
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。 输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),计算这套系统最多能拦截多少导弹。
输入
多组测试数据; 对于每组数据共有两行: 第一行一个n,表示导弹个数; 第二行表示每颗导弹的高度,以空格隔开 。
输出
每组数据一行,输出最多能拦截导弹数目;
样例输入
8 389 207 155 300 299 170 158 65
样例输出
6
此题就是求最长降序子序列。
可能有人就一脸懵逼了,最长降序子序列,我是对的呀,就是把他全部排一遍,然后选最长的么?但是位置不能变啊,一变就不对了
我百度了下,有位小伙伴解说的很清晰
链接:
http://blog.163.com/kevinlee_2010/blog/static/169820820201092091343405/
例如:有一个序列,例如 9 8 2 1 7 5 3 4 3 2 1.
求出最长的递减子序列。如本例的结果就是:9 8 7 5 4 3 2 1。
算法:
此题为动态规划经典题目,时间复杂度O(n^2)。
解法如下:
设原数组为a[1....n]。设一数组d[1....n],其中d[i]表示从第i个元素开始(一定
包含第i个元素),到整个数组末尾的子序列 a[i...n]中的最长递减子序列的长度。
则本问题就是要在求出d[1]的同时,恢复出最优解。
下面给出递推式:
d[i]的值分两种情况:
1、当i=n时,d[i]=1。即最后一个元素的序列的最大递减子序列中只有它自己。
2、当i<n时,d[i]=max{d[k]| i<k<=n 且a[i]>a[k]} +1。解释意思为,包含第i个
元素的序列a[i...n]的最大子序列依赖于i后面所有的序列中比a[i]小(满足递减
特性),且最大的d[k](满足最 优特性)值再加1(加上a[i]元素)。在给d[i]赋的时候只需记录p[i]=k,既可以作为parent属性恢复出解。
具体实现的话,开两个数组d[n],p[n],外层循环从后往前选取i,内层循环从i往
后寻找最优的k,双循环遍历即可求出所有的d[i]。然后 再进行一次O(n)操作,找
出最大的d[max]。恢复解的话,可以从p[max]开始,依次恢复出各个解。
可能还是有人一脸懵逼,看不懂,那我们再简便点:
比如,9 8 2 1 7 5 3 4 3 2 1,我们把他们放在一个数组a[100],另外设一个数组b[100],a[0]是9,再设个n=0,a[0]之前比他大的有0个,因为n<=0,b[0]=a+1,你可能会想不对呀,万一是9786,那就是3咯?不,我们可以设置个for循环来是前面的大于后面的再加一,然后一直比到1,然后求出b数组里的最大值就行了。
可能有人还是觉得有哪里不对,那么我们直接上代码,这样就能好理解一点了
就是在数组的每个数,求他们前面有多少个升序的数
会不会超时,emm,你试下就知道了
希望对初学的你有帮助