第一問,單個系統最多能攔截多少飛彈,求最長不公升序列即可.
拿出lis的模板塗塗改改.
bool cmp(const int& a, const int& b)第二問,最少需要多少個獨立的系統攔截所有飛彈.for (int i = 1; i <= n; i++)
if (s[i] <= dp[len] || !len)
dp[++len] =s[i];
else
printf(
"%d\n
", len);
飛彈的高度是有相同的,先簡化為所有資料不同.
首先猜想讓一套系統取走序列的lds(最長下降子串行),然後再來一套系統取走現在的序列的lds,直至序列為空,得到使用的系統數量.這個方法我沒有想到證明或者證偽的思路.
現在換一種思路,利用飛彈是依次 飛來的條件,第一顆飛彈x飛來時有一套裝置a攔截之,現在第二顆飛彈飛來,有:
第二顆飛彈比第一顆高:只能使用另一套裝置b攔截.
比第一顆低:可以使用裝置a攔截,也可以使用裝置b攔截.
如果明確第二種情況下選擇的方法,那麼至少可以模擬出來.先比較一下兩種選項的利弊:
使用a攔截第二顆飛彈y:"消耗"了一套系統,並使得a系統拋棄了高度位於x與y之間的後續飛彈,但仍可攔截高度低於y的後續飛彈.
使用b攔截:"消耗了"兩套系統,並使得a系統仍可攔截高度位於x與y之間的後續飛彈,且b系統可攔截高度低於y的後續飛彈.
現在"控制變數"一下,讓情況1加一套系統,那麼就變成了"消耗"了兩套系統,並使得a系統拋棄了高度位於x與y之間的後續飛彈,但仍可攔截高度低於y的後續飛彈.且新增b系統可以補充攔截x與y之間的後續飛彈.可見情況1下可以在相同消耗的情況下達到等價情況2的效果.
然而在一種特殊情況下,情況1可以在更小消耗下達到等價情況2的效果:後續飛彈高度均低於y.此時情況1只需要消耗一套系統,情況2則消耗了至少兩套系統.並且不存在這樣一種特殊情況,使得情況2可以在消耗更小的條件下達到等價情況1的效果.
因此有如下求解策略:不停地啟用一套新的系統,對於每一套系統依次嘗試攔截所有飛彈,如果可攔截則攔截,否則放棄,直到攔截所有的飛彈.
按照這個策略即可求解出最小消耗系統數,且這個數值與該飛彈高度序列的最長上公升子串行的長度相等,證明可以看這裡.這樣才能保證複雜度.
洛谷P1020 NOIP1999 攔截飛彈
題意簡述 求最長不上公升子串行的長度,並求出最少有幾個不上公升子串行。解題思路 第一問直接用dp做,有o n 2 的也有優化後o nlgn 的,我才用的是前者。第二問可以用乙個陣列h來記錄當前所有系統的攔截高度,每次遇到乙個新元素,在h陣列中找乙個大於 a i 的最小的元素,並將其更新為 h j a...
P1015 NOIP1999 普及組 回文數
題目描述 若乙個數 首位不為零 從左向右讀與從右向左讀都一樣,我們就將其稱之為回文數。例如 給定乙個十進位制數 5656,將 5656 加 6565 即把 5656 從右向左讀 得到 121121 是乙個回文數。又如 對於十進位制數 8787 step1 87 78 16587 78 165 ste...
NOIP 1999 普及組 複賽 回文數
noip 1999 普及組 複賽 回文數 1309 例1.6 回文數 noip1999 高精度加演算法,很有信心 後判斷 翻轉 先加 30步跳出 仔細看題,發現並不只是十進位制,是n進製,馬上意識到該題的難度了 過了一晚之後,再想想,只要把十進位制中的10換成n,並編寫乙個列印函式,列印位上的值大於...