导弹防御系统
题意:
最少可以找到一直 严格单调 上升或者一直 严格单调 下降
题解:
第一反应是LIS,但是本题要求找一直上升或者一直下降的,LIS不能实现
但是我们还是从LIS下手,LIS中最核心的思想是能否将一个元素加入到序列中,只与这个序列目前的最后一个元素有关
我们用up[k]和down[k]记录第k套上升(下降)系统目前所拦截的最后一个导弹
dfs(u,v,t)表示已有u个上升,v个下降,正在处理第t个数
现在我们要将一个数放入上升序列中,那么一定是所有能放入的上升序列中,最后一个元素最大的那一个,这样求答案,节省时间
因为放在最大的里面,就不会浪费小的,就把小的让给更需要的数(就是每个数都往“条件最差”的情况里放)
up[i]按照这样的策略顺序自然就是排好的,所以只能找最先碰到的一个选择
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
const int maxn=60;
int a[maxn],up[maxn],down[maxn],n;
int ans;
void dfs(int u,int d,int t)
{if(u+d>=ans)return ;if(t==n){if(u+d<ans)ans=u+d;return ;}int i;for(i=1;i<=u;i++)//找到第一个末尾数小于a[t]的导弹系统if(up[i]<a[t])break;int temp=up[i];up[i]=a[t];//添加到该导弹系统中,i有可能是之前已有的,也可能是新的导弹系统 dfs(max(u,i),d,t+1);//有可能第t个数在某个序列后面,也有可能自己成一个序列up[i]=temp;//恢复原状 for(i=1;i<=d;i++)if(down[i]>a[t])break;temp=down[i];down[i]=a[t];dfs(u,max(d,i),t+1);down[i]=temp;//恢复原状
}
int main()
{while(cin>>n&&n!=0){ans=200;for(int i=0;i<n;i++)cin>>a[i];dfs(0,0,0);cout<<ans<<endl;}return 0;
}