导弹防御系统——最长上升子序列

为了对抗附近恶意国家的威胁,R 国更新了他们的导弹防御系统。
一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。
例如,一套系统先后拦截了高度为 3 和高度为 4 的两发导弹,那么接下来该系统就只能拦截高度大于 4 的导弹。
给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。

输入
输入包含多组测试用例。
对于每个测试用例,第一行包含整数 n (1 ≤ n ≤ 50),表示来袭导弹数量。
第二行包含 n 个不同的整数,表示每个导弹的高度。
当输入测试用例 n=0 时,表示输入终止,且该用例无需处理。

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

Input
5
3 5 2 4 1
0
Output 
2

解析:
题意是 用最少的上升子序列和下降子序列来含盖整个序列。
如果用最少的上升子序列来含盖整个序列,可以用贪心的方法,对于每个数,一定在上升子序列的末尾,它要不接在已有序列中小于它最大的数的末尾,要不再开一个新序列。
同理可得,用最少的下降子序列来含盖整个序列。

但是,对于整个序列的每个数,不知道它是在上升子序列里合适,还是在下降子序列里合适。又因为数据范围较小,可以用 dfs 暴力搜索,来枚举每一个数的情况,不断更新答案。

#include 
#include 
using namespace std;
#define int long long
#define endl '\n'
#define ios ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
int gcd(int a,int b) { return b? gcd(b,a%b) : a; }
typedef pair PII;
const double PI=acos(-1.0);
const int N=51;
int n;int a[N];
int ans;
int s[N],f[N];
void dfs(int u,int l,int r)
{
    if (l+r>=ans) return ;          //剪枝
    if (u>n)
    {
        ans=l+r;
        return ;
    }
    int k=0;
    while (k=a[u]) k++;    //上升子序列,找到第一个小于 a[u] 的数
    t=f[k];                         //备份现场
    f[k]=a[u];
    if (k>n,n)
    {
        for (int i=1;i<=n;i++) cin>>a[i];
        solve();
    }
    return 0;
}

你可能感兴趣的:(算法,数据结构)