导弹防御系统
这道题和上道题的问题二相比,多了一种严格上升的导弹系统,对于两种不同的导弹系统都可以用上道题的方式来分别求解,具体的看链接:https://blog.csdn.net/2303_80682055/article/details/135374010?spm=1001.2014.3001.5501
但是!
这道题两种导弹系统放在了一起来探究,那么问题就转换成了什么时候存入上升系统,什么时候存入下降系统呢。这里我们可以用DFS来爆搜所有情况来解决这个问题。我们设上升系统的子序列末尾为up[],下降的为down[],用u和d分别来记录上升子序列和下降子序列的个数,设ans为答案,ans=d+u,我们可以通过直接剪掉d+u大于先前ans的可能性来优化代码。然后我们还需要设一个t用来dfs的回溯恢复现场用
总体思路就是这样,在上一题的解基础上加上dfs就可以写这道题,但是!这里的t必须要设成局部变量。这里的t是十分关键的,我一开始将其设为全局变量一直WA,后面问了别人才知道这里如果设成了全局变量的话,其t的值会被下面的dfs迭代给刷新,那么就无法恢复现场了
详细见代码:
#include<iostream>
using namespace std;
const int N=55;
int up[N],down[N],n,ans,a[N];
void dfs(int x,int u,int d){
if(u+d>=ans)
return;
if(x==n){
ans=u+d;
return;
}
int k;
for(k=1;k<=u;k++) //找到第一个末尾小于a[x]的上升子序列
if(up[k]<a[x])
break; //若没有则k以u+1退出循环,即增加子序列
int t=up[k];
up[k]=a[x];
dfs(x+1,max(u,k),d);
up[k]=t; //回溯回复现场
for(k=1;k<=d;k++) //与上面插入到上升子序列中一样的原理
if(down[k]>a[x])
break;
t=down[k];
down[k]=a[x];
dfs(x+1,u,max(d,k));
down[k]=t;
}
int main(){
while(cin>>n,n){
ans=100;
for(int i=0;i<n;i++) cin>>a[i];
dfs(0,0,0);
cout<<ans<<endl;
}
return 0;
}