大多数人把这题归为dp的入门题,作为dp新手我想了好久,也上网搜了题解,但网上大多的说法千篇一律,基本都是:此题思路是用一个dp数组记下所有导弹可以达到的高度,然后把当前目标的高度与dp[]中的值逐一比较,如果发现dp[]中存在一个值大于当前高度,就用当前的高度覆盖此dp[]中的这个值,如果不存在,就将当前高度加入dp[],最终所有的高度都被拦截,最终答案就是所有高度加入dp的数量。
这里存在一个疑问,但他们都没给出证明,为什么当前高度与dp[]中每一个高度比较的时候可以从头开始,而且只要碰到dp[i]大于或等于当前高度 就把当前高度赋给dp[i]?难道不要从dp[]中挑选出一个dp[k]来让当前高度覆盖吗?虽然我举了一些例子都是符合的,但怎么证明它的正确性?
又搜了一些关于此题的解题报告,也有不少人这么说:“其实认真分析一下题就回发现:每一个导弹最终的结果都是要被打的,如果它后面有一个比它高的导弹,那打它的这个装置无论如何也不能打那个导弹了,经过这么一分析,这个问题便抽象成在已知序列里找最长上升序列的问题。" 我试着用着最长上升子序列的方法做了一遍,得到了相同的结果,并且在杭电上提交获得AC,这就不是偶然了。但是,后来细想:最长上升子序列只能保证最少需要的拦截系统,但还有可能更多。我开始尝试着举反例,结果举了半天也举不出来,于是又继续找相关题解。
结果找到了这样一段话:这涉及组合数学中的Dilworth定理.基础知识我就写了.(T_T,理解基础知识的就不用看下面的内容了.)关键之处在于证明不上子序列的划分数=最长上升子序列的长度.定义一个偏序关系≤:a≤b表示a比b出现的早且a的值大于等于b的值.即最长上升子序列就是这个偏序集的链,因为后面的元素肯定比前面的大啊,无法利用这个偏序关系比较.它的不上升子序列是偏序集的链.由Dilworth定理不上升子序列的最小划分数=最长上升子序列的长度.
看了半天不知所云,但似乎用这个Dilworth定理可以证明以上的疑问,所以这里把这个题先留下吧,等以后算法学习深入了再来看此题。希望有高手看到可以用通俗点的话解释一下这个定理。。
这个题目至少有个收获: 不上升子序列的最小划分数=最长上升子序列的长度