为了对抗附近恶意国家的威胁,R国更新了他们的导弹防御系统。
一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。
例如,一套系统先后拦截了高度为 3 和高度为 4 的两发导弹,那么接下来该系统就只能拦截高度大于 4 的导弹。
给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。
Input
多组测试用例。
对于每个测试用例,第一行包含整数 n ( 1 ≤ n ≤ 50 ),表示来袭导弹数量。
第二行包含 n 个不同的整数,表示每个导弹的高度。
当输入测试用例 n = 0 时,表示输入终止,且该用例无需处理。
Output
每个测试用例输出一行:一个整数,表示所需的防御系统数量。
Sample Input
5
3 5 2 4 1
0
Sample Output
2
思路:题意大致为给定一个序列,求最少可以用多少个上升子序列和下降子序列将其表示出来。
采用dfs和LIS的贪心求法,用bfs会爆内存?因为答案最大也不可能会大于n,所以ans初始化为n。后续更新时更新ans的最小值。对每一个d[i]都有两个方向的操作。最大为2的50次方。
同时还要回溯恢复现场。
#include<bits/stdc++.h>
using namespace std;
int ans,sum;
const int N=110;
int d[N];
int up[N];
int down[N];
int n;
void dfs(int u,int su,int sd)
{
if(su+sd>=ans) return ;
if(u==n)
{
ans=su+sd;
return;
}
//1接到某一个上升序列的末尾
int k=0;
while(k<su&&up[k]>=d[u]) k++;
int t=up[k];
up[k]=d[u];
if(k<su) dfs(u+1,su,sd);
else dfs(u+1,su+1,sd);
up[k]=t;
//2放到下降序列末尾
k=0;
while(k<sd&&down[k]<=d[u]) k++;
t=down[k];
down[k]=d[u];
if(k<sd) dfs(u+1,su,sd);
else dfs(u+1,su,sd+1);
down[k]=t;
}
int main()
{
while(cin>>n,n)
{
for(int i=0;i<n;i++)
cin>>d[i];
ans=n;
dfs(0,0,0);
cout<<ans<<endl;
}
return 0;
}