Acwing187. 导弹防御系统(6-6)

106 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情

导弹防御系统-AcWing题库

题目描述

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

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

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

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

输入格式

输入包含多组测试用例。

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

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

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

输出格式

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

数据范围

1n501≤n≤50

input

5
3 5 2 4 1
0 

output

2

样例解释

对于给出样例,最少需要两套防御系统。

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

题目分析

相较于上一题的直接进行贪心判断当前数 ii 加入的序列,本题的 ii 有两种大的去向,一种是加入单调递减序列的末尾,一种是单调递加的序列末尾。

我们注意到题目数据很小,则可以采用暴力搜索 dfsdfs 的方式解决问题。

定义一个全局变量 resres 用于存储最优解。

Accept代码 [dfs O(2^n)]

#include <bits/stdc++.h>

using namespace std;

const int N = 55;
int n, h[N], up[N], dw[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 = 0;
    while (k < su && up[k] > h[u]) k ++;
    int t = up[k];
    up[k] = h[u];
    if (k < su) dfs(u + 1, su, sd);
    else dfs(u + 1, su + 1, sd);
    up[k] = t;
    
    k = 0;
    while (k < sd && dw[k] < h[u]) k ++;
    t = dw[k];
    dw[k] = h[u];
    if (k < sd) dfs(u + 1, su, sd);
    else dfs(u + 1, su, sd + 1);
    dw[k] = t;
}

int main()
{
    while (cin >> n, n)
    {
        for (int i = 0; i < n; i ++) cin >> h[i];
        
        res = n;
        dfs(0, 0, 0);
        cout << res << "\n";
    }
    return 0;
}