【dp】导弹拦截
攔截導彈
(missile.pas/c/cpp)
來源:NOIP1999(提高組) 第一題
【問題描述】
??? 某國為了防御敵國的導彈襲擊,發展出一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以后每一發炮彈都不能高于前一發的高度。某天,雷達捕捉到敵國的導彈來襲。由于該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈。
?? 輸入導彈依次飛來的高度(雷達給出的高度數據是不大于30000的正整數),計算這套系統最多能攔截多少導彈,如果要攔截所有導彈最少要配備多少套這種導彈攔截系統。
【輸入文件】missile.in
? 單獨一行列出導彈依次飛來的高度。
【輸出文件】missile.out
? 兩行,分別是最多能攔截的導彈數,要攔截所有導彈最少要配備的系統數
【輸入樣例】
389 207 155 300 299 170 158 65
【輸出樣例】
6
2
【問題分析】
有經驗的選手不難看出這是一個求最長非升子序列問題,顯然標準算法是動態規劃。
以導彈依次飛來的順序為階段,設計狀態opt[i]表示前i個導彈中攔截了導彈i可以攔截最多能攔截到的導彈的個數。
狀態轉移方程:
opt[i]=max(opt[j])+1? (h[i]>=h[j],0=<j<i)?? {h[i]存,第i個導彈的高度}
最大的opt[i]就是最終的解。
這只解決了第一問,對于第二問最直觀的方法就是求完一次opt[i]后把剛才要打的導彈去掉,在求一次opt[i]直到打完所有的導彈,但這樣做就錯了。
不難舉出反例: 6 1 7 3 2???????
錯解: 6 3 2/1/7?? 正解:6 1/7 3 2
其實認真分析一下題就回發現:每一個導彈最終的結果都是要被打的,如果它后面有一個比它高的導彈,那打它的這個裝置無論如何也不能打那個導彈了,經過這么一分析,這個問題便抽象成在已知序列里找最長上升序列的問題。
求最長上升序列和上面說的求最長非升序列是一樣的,這里就不多說了。
復雜度:時間復雜度為O(N2),空間復雜度為O(N)。
?
?
?
題意:一種導彈攔截系統的第一發炮彈能夠到達任意的高度,但是以后每一發炮彈都不能高于前一發的高度。某天,雷達捕捉
到敵國的導彈來襲。由于該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈。輸入導彈依次飛來的高
度,計算這套系統最多能攔截多少導彈,如果要攔截所有導彈最少要配備多少套這種導彈攔截系統?
?
?
分析:
第一問很簡單,就是求最長不上升子序列。對于第二問不能用貪心的方法來做,因為有反例:7 5 4 1 6 3 2.
我們把第二問的問題抽象出來,那就是:把一個數列劃分成最少的最長不升子序列,這里我們要介紹一個很優美的定理。
?
Dilworth定理:對于一個偏序集,最少鏈劃分等于最長反鏈長度。
Dilworth定理的對偶定理:對于一個偏序集,其最少反鏈劃分數等于其最長鏈的長度。
?
也就是說把一個數列劃分成最少的最長不升子序列的數目就等于這個數列的最長上升子序列的長度。
?
下面來說說這個定理是怎么來的:
?
偏序集的定義:偏序是在集合X上的二元關系≤(這只是個抽象符號,不是“小于或等于”,它滿足自反性、反對稱性和傳遞
性)。即,對于X中的任意元素a,b和c,有:
?
(1)自反性:a≤a;
(2)反對稱性:如果a≤b且b≤a,則有a=b;
(3)傳遞性:如果a≤b且b≤c,則a≤c 。
?
帶有偏序關系的集合稱為偏序集。
?
?
令(X,≤)是一個偏序集,對于集合中的兩個元素a、b,如果有a≤b或者b≤a,則稱a和b是可比的,否則a和b不可比。
在這個例子(反鏈)中元素Ri<=Rj是指(i<=j) and (ai>=aj)
?
一個反鏈A是X的一個子集,它的任意兩個元素都不能進行比較。
一個鏈C是X的一個子集,它的任意兩個元素都可比。
?
【定理】
在X中,對于元素a,如果任意元素b,都有a≤b,則稱a為極小元。
定理1:令(X,≤)是一個有限偏序集,并令r是其最大鏈的大小。則X可以被劃分成r個但不能再少的反鏈。
?
其對偶定理稱為Dilworth定理:
令(X,≤)是一個有限偏序集,并令m是反鏈的最大的大小。則X可以被劃分成m個但不能再少的鏈。
雖然這兩個定理內容相似,但第一個定理證明要簡單一些。此處就只證明定理1。
?
證明:設p為最少反鏈個數
(1)先證明X不能劃分成小于r個反鏈。由于r是最大鏈C的大小,C中任兩個元素都可比,因此C中任兩個元素都不能屬于同一反
鏈。所以p>=r。
(2)設X1=X,A1是X1中的極小元的集合。從X1中刪除A1得到X2。注意到對于X2中任意元素a2,必存在X1中的元素a1,使得
a1<=a2。令A2是X2中極小元的集合,從X2中刪除A2得到X3……,最終會有一個Xk非空而Xk+1為空。于是A1,A2,…,Ak就是X的
反鏈的劃分,同時存在鏈a1<=a2<=…<=ak,其中ai在Ai內。由于r是最長鏈大小,因此r>=k。由于X被劃分成了k個反鏈,因此
r>=k>=p。
(3)因此r=p,定理1得證。
?
【解決】
要求最少的覆蓋,按照Dilworth定理
最少鏈劃分 = 最長反鏈長度
所以最少系統 = 最長導彈高度上升序列長度。
?
?
?
1 #include<bits/stdc++.h> 2 3 int arr[1000010]; 4 int dp[1000010]; 5 6 int main(){ 7 int n; 8 while(~scanf("%d", &n)){ 9 for(int i = 0; i < n; i++) scanf("%d", &arr[i]); 10 11 for(int i = 0; i < n; i++) dp[i] = 1; 12 for(int i = 1; i < n; i++){ 13 for(int j = 0; j < i; j++){ 14 if(arr[i] <= arr[j] && dp[j]+1 > dp[i]) dp[i] = dp[j]+1; 15 } 16 } 17 int ans = 0; 18 for(int i = 0; i < n; i++) if(ans < dp[i]) ans = dp[i]; 19 printf("%d\n", ans); 20 21 for(int i = 0; i < n; i++) dp[i] = 1; 22 for(int i = 1; i < n; i++){ 23 for(int j = 0; j < i; j++){ 24 if(arr[i] > arr[j] && dp[j]+1 > dp[i]) dp[i] = dp[j]+1; 25 } 26 } 27 ans = 0; 28 for(int i = 0; i < n; i++) if(ans < dp[i]) ans = dp[i]; 29 printf("%d\n", ans); 30 } 31 32 return 0; 33 }?
轉載于:https://www.cnblogs.com/miaowTracy/p/5927744.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: 清北学堂十一培训酱油记
- 下一篇: 优美三角剖分_递归