POJ 3700 Missile Defence System

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
Hint

Two sets of systems are needed for the sample. One brings down 3, 4 and the other brings down 5, 2, 1.


题意:给一些高度不同的导弹,一套拦截系统拦截的高度要么可以一直下降,要么可以一直上升。问最少需要多少套拦截系统可以覆盖所有的导弹。

对于每枚导弹,有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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值