HDU 1257 最少拦截系统【LIS】

题意:类似于套娃娃,问最少需要多少个拦截系统。

思路:

假设已经有m个导弹拦截序列

r1:x11>=x12>=x13>=...>=x1n

r1:x21>=x22>=x23>=...>=x2n
.

.

rm:xm1>=xm2>=xm3>=...>=xmn

则必定有有一个序列x1i<x2i<x3i<...<xmi,证明:

若rx中最小比他后边某个序列的所有元素都要大的话,这两个序列必定能合成一个序列。

如r1:8,5,4

 r2:3,2,1

因此序列x1i<x2i<x3i<...<xmi的长度就是所求的长度。

另,原序列的最长严格上升序列的长度的就是该序列的长度。证明:

若存在最长严格上升子序列:xj1<xj2<xj3<...<xjk

很明显,则xj2与xj1不可能属于同一个r,后同。故得证。

故原问题就转换成求最长严格上升子序列的长度。

类似的题目还有:http://acm.hdu.edu.cn/showproblem.php?pid=1677

以上结论的证明是本人第一次完全靠自己写的证明,必定有所纰漏,甚至完全错误。写在此并不是为了让看官们背住结论就算了,更希望许多像我一样的菜鸟能够自己动手证明一些东西,这样你对于这个知识点的理解必定会上一层楼。希望大神们指正。

#include<stdio.h>
#include<string.h>
const int N=1111;
int a,d[N];
int main(){
    int n,i,ans;
    while(~scanf("%d",&n)){
        d[0]=-1;ans=0;
        for(i=1;i<=n;i++){
            scanf("%d",&a);
            if(a>d[ans]){
                d[++ans]=a;
            }else{
                int l=1,r=ans;
                while(l<=r){
                    int mid=(l+r)>>1;
                    if(d[mid]>a)    r=mid-1;
                    else            l=mid+1;
                }
                d[l]=a;
            }
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/L-King/p/5763989.html