題意:有一種攔截系統,可以打擊導彈,但是打擊的高度會逐漸下降,因此為了防御導彈攻擊,就必須用多個系統,現給出一列導彈依次的高度,求最少需要的系統數。
這道題是最長上升子序列問題,但是我一開始其實並沒有想到,最開始我的思路是依次剔除最長下降子序列,每剔除一輪就是需要一個攔截系統,然后直到全部數都剔除了就可以知道要幾個攔截系統了。而且這樣做就是最長下降子序列符合 dp 的思路也可以自圓其說,所以說為什么我成長得這么慢,其實就是我刷 dp 專題就使勁往怎么用 dp 上想而不是怎么做出來上想,很多時候這樣其實我的進步還是太小。
恩,這樣做 WA 了,我也不是很清楚為什么 WA ,但是我在這么敲的時候就覺得這種思路其實很亂,就這么 A 了其實對我也不太好吧。
WA 了就知道要找新辦法了,於是我想到了另一種做法,邊遍歷數字邊建系統,對於一個數字,如果之前建立過的系統中有最小值大於這個數字的,那么就說明那個系統可以攔截這枚導彈,那么就把該攔截系統的最小值改為這個數字,而如果這個數字大於所有之前攔截系統的最小值的話,那就說明沒有系統可以攔截這枚導彈了,我就重新建立一個系統,其最小值就是當前數字。其實我並不知道到底是不是對的,因為有一點需要考慮,當有很多系統都能攔截它時,我該優化哪一個呢,我選擇了最小的,顯然我也不知道這樣對不對。然后我 A 了```不甘心地 A 了```
問過學長之后,學長告訴我,其實就只是一個最長上升子序列。細想一下,對於這個最長上升子序列而言,每一個數代表一個攔截系統的最小值,並且由於序列是上升的,每一個數都不能再攔截序列中的下一個數,因為下一個數更大,因此這個子序列的長度就是攔截系統數。我覺得這個說法我更能接受,或許之前那個做法只是因為數據弱所以就這么過了吧```
就這樣,我感覺我和數據一樣弱```
蠢,就是蠢!

1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 int dp[30001],a[30001]; 6 int main(){ 7 int n; 8 while(scanf("%d",&n)!=EOF){ 9 int i,j,c=0; 10 memset(dp,0,sizeof(dp)); 11 for(i=1;i<=n;i++){ 12 scanf("%d",&a[i]); 13 int f=0; 14 for(j=1;j<=c;j++){ 15 if(a[i]<dp[j]){ 16 f=1; 17 dp[j]=a[i]; 18 break; 19 } 20 } 21 if(!f)dp[++c]=a[i]; 22 sort(dp+1,dp+c+1); 23 } 24 printf("%d\n",c); 25 } 26 return 0; 27 }