拦截导弹 最长上升/下降子序列
題意, 長度為n的序列, a1,a2, ...,ai, ..., an, ?求最長嚴格上升子序列長度,與最長下降非嚴格自序列長度.
?
解法: ? ? 首先不得不吐嘈下題目的讀入,惡心指數上達5顆星.
對于一套攔截系統最多能攔截多少導彈, 求個非嚴格下降子序列就可以了.就不廢話了. 主要還是求最少攔截數量.
有一個結論, 最少攔截系統數量為 嚴格上升子序列. ?思路如下:
假定一個最長上升子序列形式如: ? ?...a_i ... aj ?...?
對于 ?a_i 與 a_j 之間的數 x 只可能有兩類, ?x <= a_i , 則可以 將這些導彈劃分到 a_i攔截系統, x >= aj, 則可以將這些導彈劃分到 a_j攔截系統.
其它區間類似. ??其中還有如下情況, ? ?b_1, b_2, <= a_i, ?但是 ?b_1 > b_2, ?那么b_1,b_2必定不能歸結于一個攔截系統, 但是必定可以被 a_i之前的系統攔截.
O(N^2) 代碼實現, ?
令 g( i ), 表示前i個導彈, 取第i個的最大長度.
dp(i), 表示前i個導彈, 最長上升子序列長度.
g(i) = max( 1, g(j) ) ? a_i > a_j
dp(i) = max( dp(i-1), g(i) )?
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std;const int N = 101000;int g[N], dp[N], n, a[N];int main(){n = 0; // scanf("%d", &n); // for(int i = 0; i < n; i++) scanf("%d", a+i ); while( scanf("%d",&a[n] ) != EOF ) n++;dp[0] = 0; for(int i = 1; i <= n; i++){g[i] = 1;for(int j = i-1; j >= 1; j-- )if( a[i-1] <= a[j-1] ) g[i] = max( g[i], g[j]+1 );dp[i] = max( dp[i-1], g[i] ); }printf("%d\n", dp[n] );dp[0] = 0;for(int i = 1; i <= n; i++){g[i] = 1;for(int j = i-1; j >= 1; j-- )if( a[i-1] > a[j-1] ) g[i] = max( g[i], g[j]+1 );dp[i] = max( dp[i-1], g[i] );}printf("%d\n", dp[n] ); return 0; } View CodeO(NlogN)的寫法,前面寫過的題目里頭有, 就懶得貼了.
轉載于:https://www.cnblogs.com/yefeng1627/archive/2013/05/13/3076890.html
總結
以上是生活随笔為你收集整理的拦截导弹 最长上升/下降子序列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云南省行政村谷歌图层_云南省基本农田划定
- 下一篇: 2.2数据通信的基础知识