[NOIP1999]拦截导弹

这里写图片描述

又是一道动态规划题

**

【算法分析】

**

第一问即典型的最长不下降子序列问题,可以用一般的DP算法,也可以用高效算法,但这个问题的数据规模并不需要。 用a[x]表示原序列中第x个元素,b[x]表示长度为x的不下降子序列的长度。当处理a[x]时,可查找它可以连接到长度最大为多少后(即与部分b[x]比较)。假设可以连接到长度最长为maxx的不下降子序列后,则b[x]=maxx+1。b数组被赋值的最大值就是第一问的答案。

第二问贪心法也是可以的。每颗导弹来袭时,使用能拦截这一颗导弹的防御系统中上一次拦截导弹高度最低的那一套来拦截。如不存在符合这一条件的防御系统,则使用导弹系统数量+1。

**

【参考代码】(顺推)

**

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    int i,x,n,M,m,a[10005],b[10005],h[10005];
    i=1;n=0;m=0;
    memset(a,0,sizeof(a));  
    memset(b,0,sizeof(b));
    memset(h,0,sizeof(h));
    while(cin>>a[i])
    {
        M=0;
        for(int j=1;j<=i-1;j++)//计算前i-1个导弹最佳拦截方式
        if(a[j]>=a[i])
            if(b[j]>M)
            M=b[j];
        b[i]=M+1;//在前i-1个导弹最佳拦截方式上+1
        if(b[i]>m)   m=b[i];
            x=0;
        for(int k=1;k<=n;k++)//计算由哪一套系统拦截导弹
        if(h[k]>=a[i])
        if(x==0)    x=k;
            else
        if(h[k]<h[x])    x=k;
                //如果有多余的系统可拦截,则选择上一次拦截高度最低的
        if(x==0)    {n++;x=n;}  // 新增一套导弹拦截系统
            h[x]=a[i];
        i++;
    }
    printf("%d\n%d\n",m,n);
}

或者

#include<cstdio>
int main()
{
    int in[100005],n=0,U[100005],D[100005],a=-1,b=-1;
    while(scanf("%d",&in[++n])==1)
    {
        U[n]=D[n]=1;
    }
    for(int i=1;i<n;i++)
        for(int j=1;j<i;j++)
        {

            if(in[j]<in[i]&&U[j]+1>U[i])
                U[i]=U[j]+1;

            if(in[j]>in[i]&&D[j]+1>D[i])
                D[i]=D[j]+1;
        }
    for(int i=1;i<n;i++)
    {
        if(U[i]>a)a=U[i];
        if(D[i]>b)b=D[i];
    }
    printf("%d\n%d",b,a);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值