题目连接:https://www.dotcpp.com/oj/problem1627.html
来源:C语言网
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹 拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的 导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入
一行,为导弹依次飞来的高度
输出
两行,分别是最多能拦截的导弹数与要拦截所有导弹最少要配备的系统数
样例输入
389 207 155 300 299 170 158 65
样例输出
6
2
思路一:输入坑死…,我们可以发现最多能够拦截的导弹就是最长不上升子序列的个数,要拦截所有的导弹就是最长上升子序列,因为要把序列分成若干段不上升的,那么段与段之间一定存在上升,所以我们找到最长上升子序列就可以拦截到所有的导弹。 d p [ i ] dp[i] dp[i] 用来表示以 i i i 结尾的最长不上升/上升子序列的长度。
#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;
}
思路二:对于上述问题,其实我们可以优化,用 d p [ i ] dp[i] dp[i] 来表示长度为 i i i 的末尾是 d p [ i ] dp[i] dp[i]
对于不上升的子序列来说,这个末尾就是一个最大的末尾
- 300 200 100 假如第三个数是200,那么此时 d p [ i ] dp[i] dp[i] 的末尾就是 200(因为要保证最长),通过 lower_bound 找到 <=200 的第一个数,然后用来代替 100
对于上升的子序列来说,这个末尾就是一个最小的末尾
- 100 300 假如第三个数是200,那么此时那么此时 d p [ i ] 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;
}