动态规划——拦截雷电箭(导弹拦截)

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
#define For(a,begin,end)  for(register int a=begin;a<end;a++)
int main()
{   //寻找最长的降序数列->我们只需要长度!!!
    // freopen("1.in","r",stdin);!!!
    vector <int> s,d,d2;
    int n,h;
    n=1;
    while(cin>>h)//ctrl+z
    {
        n++;
        s.push_back(h);
    }
    n--;
    d.push_back(*s.begin());
    d2.push_back(*s.begin());
    //目的是找到一个最长的下降序列(准确->不上升)
    //于是我们改变d[i]的定义-> i为长度时,最优的结尾元素->就是d[i]
    //但是整个数列并不是最长的下降序列(虽然长度是对的 r:33-36)
    For(i,1,n)
    {
        if(s[i]<=d.back())
            d.push_back(s[i]);
        else{
            //使用upper_bound()  返回第一个大于查找值的指针 ,(升序数列)
            //当我们加上 greater<int>() 时,返回第一个小于查找值的指针
            //用s[i]替换这个值(因为s[i]比它大,因此我们可以在数组里储存更多的数字)
            //这个操作导致我们的d[]就可能不是最长的下降序列了
            //我们把比最小值大的数移到了它前面,但是呢又不改变其长度,又可以扩充其空间,
            //使其之后可以容纳更多的数字->相当于数字之间更紧密了(往左看时)
            /*某种往左靠的精准*/
            *upper_bound(d.begin(),d.end(),s[i],greater<int>()) =s[i];
        }
        if(s[i]>d2.back())
            d2.push_back(s[i]);
        else{//lower_bound 找第一个>=ta的,然后换掉
            *lower_bound(d2.begin(),d2.end(),s[i])=s[i];
        }
    }
    cout<<d.size()<<"\n"<<d2.size();
    return 0;
}

感觉dp优化到比较精妙的时候,似乎算法就有点像人类的思考方式一样了,不过计算机是一遍找完,而我们可能需要反复猜想论证,最终得出正确结果。

比如此题寻找最长的下降序列,如果我不是靠计算机解决这个问题的话,那么我也会尽量找到两个最接近的数在一起,因为这样就能存更多的数了,但是数一多起来就又做不下去了,因此上面的“替换”代码就很具有思考价值了。


描述

莱尼尔是海鲁拉大地之中最强的怪兽之一,无论近战还是远程攻击,莱尼尔都近乎完美。

莱尼尔最令人闻风丧胆的远程攻击是箭雨,这是一种能够动态跟踪对手所在位置的空对地攻击。无论距离多远,只要箭雨飞出,打击必达。

为了能够完美抵御莱尼尔的箭雨,约珥开发了一种箭雨拦截系统,可以发射出若干海鲁拉盾,在空中拦截莱尼而的箭雨。于此同时,整个拦截系统可以透过ambo的方式传送给林克。

但是每套箭雨拦截系统有一个缺陷:第一面地对空的发射的海鲁拉盾可以到达任意的高度,但是以后每一面海鲁拉盾都不能高于前一面的高度。

在实际战斗中,已知莱尼尔射出的箭雨阵中每一支雷电箭依次飞来的高度(高度数据是≤50000的正整数)。

请计算每套箭雨拦截系统最多能拦截多少支雷电箭?

如果要拦截所有雷电箭,林克最少要配备多少套这种雷电箭拦截系统?

输入
1行,若干个整数(个数≤100000)

注意:共有20组测试数据,前10组N^2算法可AC,后10组需要n(logn)算法。

输出
2行,每行一个整数。

第一个数字表示这套箭雨系统最多能拦截多少雷电箭。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章