187. 导弹防御系统
题意
为了对抗附近恶意国家的威胁,R 国更新了他们的导弹防御系统。
一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。
例如,一套系统先后拦截了高度为 3 和高度为 4 的两发导弹,那么接下来该系统就只能拦截高度大于 4 的导弹。
给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。
思路
和 AcWing 1010. 拦截导弹 很类似的一题 唯一不同的是不仅可以选择上升子序列 也可以选择下降子序列
因为数据非常的小 所以我们选择爆搜 对于每一个元素 分为两种情况
一种是选择把它放到结尾元素小于当前数的最大的上升子序列中
另一种是放到结尾元素大于当前数的最小的下降子序列中
注意每次搜完之后要恢复现场
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define mod 998244353
#define endl '\n'
using namespace std;
typedef long long LL;
typedef pair<int, int>PII;
const int N = 6000;
int n;
int a[N], up[N], down[N];
int res;
void dfs(int u, int su, int sd) {
if (su + sd >= res)return;
if (u == n) {
res = su + sd;
return;
}
//第一种情况 将当前数放在上升子序列后面
int k = 1;
while (k <= su && a[u] <= up[k])k++;
int t = up[k];
up[k] = a[u];
if (k <= su)dfs(u + 1, su, sd);
else dfs(u + 1, su + 1, sd);
up[k] = t;
//第二种情况 将当前数放在下降子序列后面
k = 1;
while (k <= sd && a[u] >= down[k])k++;
t = down[k];
down[k] = a[u];
if (k <= sd)dfs(u + 1, su, sd);
else dfs(u + 1, su, sd + 1);
down[k] = t;
}
void solve() {
while (cin >> n, n) {
for (int i = 0; i < n; ++i)scanf("%d", a + i);
res = INF;
dfs(0, 0, 0);
cout << res << endl;
}
}
int main() {
//int t; cin >> t;
//while (t--)
solve();
return 0;
}