Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 4418 Accepted: 1072
Description
To play against the threats of malicious countries nearby, Country R has updated their missile defence system. The new type system can bring down a series of missiles as long as they are coming in ascending order by altitude or descending order by altitude.
Given the heights of a sequence of coming missiles, the general wants to know how many sets of the new type systems are needed to bring down all of them.
Input
The input consists of several test cases. The first line of each test case contains an integer n(1 ≤ n ≤ 50). The next line contains n different integers indicating the heights.
Output
For each test case output a single line containing the number of systems needed.
Sample Input
5
3 5 2 4 1
0
Sample Output
2
【分析】
自己的程序记录状态太多给T了,懒得重构代码,抄一下rlt的。
题意:给一些高度不同的导弹,一套拦截系统拦截的高度要么可以一直下降,要么可以一直上升。问最少需要多少套拦截系统可以覆盖所有的导弹。
对于每枚导弹,有4种决策:跟随前面一个已经建好的升序拦截系统、跟随一个降序拦截系统、新开一个升序系统拦截、新开一个降序系统拦截。
所需拦截系统的最大值不会很大,可以用迭代加深搜索。
运用贪心进行剪枝:当一个导弹能够跟随一个升(降)序系统时,就不需要再枚举新开一个系统了,因为这个导弹迟早是要拦截的,不如先用以前的系统拦截了再说。也不需要枚举跟随哪一个系统,如果跟随一个升(降)序拦截系统,就找末尾导弹高度最大(小)的。
最终搜索实际上只需要考虑跟随一个升序系统或降序系统两个分支,仅在不能跟随时考虑新建。
【代码】
#include<iostream>
#include<cstdio>
using namespace std;
int n,dep,h[105],a[105],b[105];
bool dfs(int cur,int zeng,int jian)//第cur发导弹,有zeng组上升,jian组下降
{
if(zeng+jian>dep)//超过深度
return 0;
if(cur>n)//答案更优
return 1;
int k=0,mx=0,mn=1e9+7,tmp;
for(int i=1;i<=zeng;i++)//找不超过它的最大
if(a[i]<h[cur]&&mx<a[i])
{
k=i;
mx=a[i];
}
if(k)//找到,继续搜索
{
tmp=a[k];
a[k]=h[cur];
if(dfs(cur+1,zeng,jian))
return 1;
a[k]=tmp;
}
else//否则兴建一组
{
a[zeng+1]=h[cur];
if(dfs(cur+1,zeng+1,jian))
return 1;
}
k=0;
for(int i=1;i<=jian;i++)
if(b[i]>h[cur]&&mn>b[i])
{
k=i;
mn=b[i];
}
if(k)
{
tmp=b[k];
b[k]=h[cur];
if(dfs(cur+1,zeng,jian))
return 1;
b[k]=tmp;
}
else
{
b[jian+1]=h[cur];
if(dfs(cur+1,zeng,jian+1))
return 1;
}
return 0;
}
int main()
{
while(scanf("%d",&n)&&n)
{
for(int i=1;i<=n;i++)
scanf("%d",h+i);
for(int i=1;;i++)
{
dep=i;
if(dfs(1,0,0))
{
printf("%d\n",i);
break;
}
}
}
return 0;
}