問題 1627: [藍橋杯][算法訓練VIP]攔截導彈( LIS + STL)

題目連接:https://www.dotcpp.com/oj/problem1627.html
來源:C語言網

題目描述
  某國爲了防禦敵國的導彈襲擊,發展出一種導彈 攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的 導彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈。
  輸入導彈依次飛來的高度(雷達給出的高度數據是不大於30000的正整數),計算這套系統最多能攔截多少導彈,如果要攔截所有導彈最少要配備多少套這種導彈攔截系統。
輸入
  一行,爲導彈依次飛來的高度
輸出
  兩行,分別是最多能攔截的導彈數與要攔截所有導彈最少要配備的系統數
樣例輸入
  389 207 155 300 299 170 158 65
樣例輸出
  6
  2

  思路一:輸入坑死…,我們可以發現最多能夠攔截的導彈就是最長不上升子序列的個數,要攔截所有的導彈就是最長上升子序列,因爲要把序列分成若干段不上升的,那麼段與段之間一定存在上升,所以我們找到最長上升子序列就可以攔截到所有的導彈。dp[i]dp[i] 用來表示以 ii 結尾的最長不上升/上升子序列的長度。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=3e4+10;
int a[maxn],dp[maxn],dp1[maxn];//以i結尾的最長不上升子序列的長度 

int main(){
	//char b='a'; 
	int n=0;
	/*while(b!='\n'){
		scanf("%d",&a[n++]);
		b=getchar();
	}*/
	while(~scanf("%d",&a[n])) n++;
	//for(int i=0;i<n;i++) cout<<a[i]<<" ";
	int mmax1=-1,mmax2=-1;
	for(int i=0;i<n;i++){//當前數 
		dp[i]=1; dp1[i]=1;
		for(int j=0;j<i;j++){
			if(a[i]<=a[j]) dp[i]=max(dp[i],dp[j]+1);
			else dp1[i]=max(dp1[i],dp1[j]+1);
		}
		mmax1=max(mmax1,dp[i]);
		mmax2=max(mmax2,dp1[i]);
	}
	printf("%d\n%d\n",mmax1,mmax2);
	return 0;
} 

  思路二:對於上述問題,其實我們可以優化,用 dp[i]dp[i] 來表示長度爲 ii 的末尾是 dp[i]dp[i]

  對於不上升的子序列來說,這個末尾就是一個最大的末尾

  • 300 200 100 假如第三個數是200,那麼此時 dp[i]dp[i] 的末尾就是 200(因爲要保證最長),通過 lower_bound 找到 <=200 的第一個數,然後用來代替 100

  對於上升的子序列來說,這個末尾就是一個最小的末尾

  • 100 300 假如第三個數是200,那麼此時那麼此時 dp[i]dp[i] 的末尾就是 200(因爲要保證最長),通過 lower_bound 找到 >=200 的第一個數,然後用來替代 300
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=1e3+10;
int a[maxn],dp[maxn],dp1[maxn];//表示長度爲i的最小末尾是dp[i]

int main(){
	//char b='a'; 
	int n=0;
	/*while(b!='\n'){
		scanf("%d",&a[n++]);
		b=getchar();
	}*/
	while(~scanf("%d",&a[n])) n++;
	int len=0,len1=0;
	dp[len++]=dp1[len1++]=a[0];
	for(int i=1;i<n;i++){
		if(a[i]<=dp[len-1]) dp[len++]=a[i];
		else{
			int inx=lower_bound(dp,dp+len,a[i],greater<int>())-dp;
			dp[inx]=a[i];
		}
		if(a[i]>dp1[len1-1]) dp1[len1++]=a[i];
		else{
			int inx=lower_bound(dp1,dp1+len1,a[i])-dp1;
			dp1[inx]=a[i];
		}
	}
	printf("%d\n%d\n",len,len1);
	return 0;
} 
發佈了165 篇原創文章 · 獲贊 67 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章