导弹防御系统

为了对抗附近恶意国家的威胁,R 国更新了他们的导弹防御系统。

一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。

例如,一套系统先后拦截了高度为 3 和高度为 4 的两发导弹,那么接下来该系统就只能拦截高度大于 4 的导弹。

给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。

输入格式
输入包含多组测试用例。

对于每个测试用例,第一行包含整数 n,表示来袭导弹数量。

第二行包含 n 个不同的整数,表示每个导弹的高度。

当输入测试用例 n=0 时,表示输入终止,且该用例无需处理。

输出格式
对于每个测试用例,输出一个占据一行的整数,表示所需的防御系统数量。

数据范围
1≤n≤50
输入样例:
5
3 5 2 4 1
0
输出样例:
2
样例解释
对于给出样例,最少需要两套防御系统。

一套击落高度为 3,4 的导弹,另一套击落高度为 5,2,1 的导弹。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>

using namespace std;
const int N = 51;

int num[N];//高度数组
int n;//导弹个数
int f[N];//贪心的下降子序列的末尾元素
int g[N];//贪心的上升子序列的末尾元素
int cnt;//需要的系统数



void dfs(int it, int us, int ds)//dfs深搜
{
	if (us + ds >= cnt)return;//剪枝
	if (it == n) {
		cnt = us + ds;//找到一种方案更新一下系统数
		return;
	}
	//不断下降的深搜,贪心
	int k = 0;
	while (k<us && f[k]>=num[it])k++;
	int t = f[k];
	f[k] = num[it];

	if (k >= us)dfs(it + 1, us + 1, ds);
	else dfs(it + 1, us, ds);
	f[k] = t;//还原元素,为了下次深搜

	//不断上升的深搜,贪心
	k = 0;
	while (k < ds && g[k] <= num[it])k++;
	t = g[k];
	g[k] = num[it];
	if (k >= ds)dfs(it + 1, us, ds + 1);
	else dfs(it + 1, us, ds);
	g[k] = t;

}
int main()
{
	while (cin >> n, n) {
		for (int i = 0; i < n; i++)cin >> num[i];
		cnt = n;
		dfs(0, 0, 0);

		printf("%d\n", cnt);
	}

}
posted @ 2021-07-26 20:05  empty_thought  阅读(184)  评论(0)    收藏  举报