動態規劃——攔截雷電箭(導彈攔截)

#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行,每行一個整數。

第一個數字表示這套箭雨系統最多能攔截多少雷電箭。

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