[NOIP1999]拦截导弹

来源:互联网 发布:hp p2035n端口 编辑:程序博客网 时间:2024/06/03 21:55

这里写图片描述

又是一道动态规划题

**

【算法分析】

**

第一问即典型的最长不下降子序列问题,可以用一般的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);}
原创粉丝点击