导弹拦截题解(dp+Dilworth定理)

本文探讨了导弹拦截问题的两种算法实现方法:贪心算法和基于Dilworth定理的方法。贪心算法通过维护一系列不下降子序列来寻找最长上升子序列,而Dilworth定理方法则将问题转化为寻找最长上升子序列的等价问题。

在这里插入图片描述
在这里插入图片描述
导弹拦截
本题的第一问为最长不上升子序列,重点在于第二问。
第二问可分为两种做法
1.贪心做法
用如下方式维护数组g,数组长度cnt,意为cnt个不下降子序列。保存的是每一个不上升子序列中的最后一个数:
遍历原序列,对于遍历到的每一个数x:
1.若x大于g中每一个数,则新建一个不上升子序列,放入x;
2.否则,找到g中大于等于x的最小的数,将其替换。
由于g每次增加长度时,增加的数必然大于其前面g中的任何一个数;且每次替换时,不改变x与被替换数左右相邻两数的相对大小关系,故g必然维持单调递增。则g即为原序列的最长上升子序列。

     int cnt=0;                              //数组g记录的是每个不升序列结尾的最小值
    for(int i=0;i<cnt;i++)
    {
        int k=0;
        while(k<cnt&&a[i]>g[k]) k++;
        
        g[k]=a[i];
        if(k==cnt) cnt++;
    }

2.运用Dilworth定理做法
原链最长长度=反链划分数最小值
何为反链?

最长上升子序列<=>不升子序列最小划分数
最长下降子序列<=>不降子序列最小划分数

本题要求的是不升子序列即将题目转化为求上升子序列即可。

 for(int i=0;i<cnt;i++)
    {
        f[i]=1;
        for(int j=0;j<i;j++)
            if(a[i]>a[j])
            f[i]=max(f[i],f[j]+1);
        
        res=max(f[i],res);
    }
    cout<<res;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值