这道题就是一道在已有的拦截系统里查找的题,因为每一套拦截系统在导弹飞来之时会判断能否拦截,并更新每一套拦截系统可拦截的最大高度。最后把计数的cnt输出即可,是一道贪心策略的题目,感觉难度还可以。
但是今天这道题目可真是给我这个小白难坏了。
描述
为了对抗附近恶意国家的威胁,R国更新了他们的导弹防御系统。
一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。
例如,一套系统先后拦截了高度为3和高度为4的两发导弹,那么接下来该系统就只能拦截高度大于4的导弹。
给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。
输入格式
输入包含多组测试用例。
对于每个测试用例,第一行包含整数n,表示来袭导弹数量。
第二行包含n个不同的整数,表示每个导弹的高度。
当输入测试用例n=0时,表示输入终止,且该用例无需处理。
输出格式
对于每个测试用例,输出一个占据一行的整数,表示所需的防御系统数量。
数据范围
1≤n≤50
输入样例:
5
3 5 2 4 1
0
输出样例:
2
样例解释:
对于给出样例,最少需要两套防御系统。
一套击落高度为3,4的导弹,另一套击落高度为5,2,1的导弹。
题解:这道题网上大佬的解析很多,我作为小白也没有什么太深入的理解,可能有些错误认识。这里仅仅记录自己的一个学习过程。
首先我们看题,可以知道,有的导弹可以上升,也有的可以下降,所以我们不能像上道题那样,仅仅去记录多少组上升子序列的问题。
我想到的就是枚举然后去暴搜;
一个导弹的高度是应该放在递增的序列还是递减的序列,然后放到哪一个递增或者递减序列之中,就是要核心讨论的问题。
这个题对时间复杂度有要求,所以在搜索的过程要时刻想办法优化,在适当的地方去剪枝。
搜索:
- 第一种搜索可能就是BFS,宽度优先,网上有大佬用这种方法,但介于内存储存的一些写法我不太明白,就不多说了;
- 第二种就DFS,就是我采用的方法,因为在剪枝的过程确实很好写,我就只能想到这个方法了,然后可以采用声明全局最小值记录和迭代深搜两种思路,时间复杂度都是n*2^n,所以我就用前者来写这个代码。
因为小白也不怎么会,可能注释写的比较繁琐,代码如下:
#include <iostream>
using namespace std;
const int N = 100;
int n;
int q[N];
int up[N],down[N];
int ans;
void dfs(int x,int su,int sd)
{
if(su + sd >= ans) return ;
if(x==n)
{
ans = su + sd;
return ;
}
int k =0;
while(k < su && up[k] >= q[x]) k++;
int t=up[k];
up[k] = q[x];
if(k < su) dfs(x+1,su,sd);
else dfs(x+1,su+1,sd);
up[k] = t;
k = 0;
while(k < sd && down[k] <= q[x]) k ++;
t = down[k];
down[k] = q[x];
if(k < sd) dfs(x+1,su,sd);
else dfs(x+1,su,sd+1);
down[k] = t;
}
int main()
{
while(cin >> n&& n)
{
for(int i=0;i<n;i++)
cin >> q[i];
ans=n;
dfs(0,0,0);
cout<<ans<<endl;
}
return 0;
}
这个题我觉得对我来说是挺难的,也借鉴了许多网上大佬的思路,仅用来记录自己的学习过程吧。
新手上路,多多包涵。