dp求解导弹拦截问题

来源:互联网 发布:淘宝hd停止服务 编辑:程序博客网 时间:2024/06/08 14:49
Problem
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够达到任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在使用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。 

Input
最多20个整数,分别表示导弹依次飞来的高度(雷达给出高度数据是不大于30000的正整数) 

Output
两个整数M和N。表示:这套系统最多能拦截 M 枚导弹,如果要拦截所有导弹最少要配备 N 套这种导弹系统。 

Sample Input
300 250 275 252 200 138 245

Sample Output
5 2

递推公式如下:



/*    功能:求最长递减序列的元素个数以及最长非递减序列的元素个数    开发环境:Codeblocks 16.01    作者:发烧的小龙虾    日期:2017.9.25    解题思路:这题有两问,第一问要我们求输入序列的最长递减序列的元素个数。可以用动态规划的思想来求解,本人用了两种方法进行求解,一个是递归算法,一个是非递归算法,但是两种算法的思想都是基于一个递归函数来实现的。设一个数组dp[],其中dp[i]表示的是以dp[i]为递减序列的最后一个元素时这个递减序列的元素个数。当i=0时,显然dp[i]=dp[0]=1;当i不等于0时,就应该找出从编号为k(k=0,1,...i-1)的元素中找出所有满足h[k]<h[i]的元素集合,并找出这些元素集合中dp值最大的那一个作dp[i]的值。对于第二问,只需要找出最长非递减序列的个数就行了,因为最长非递减序列中任意两个元素都不可能被同一个系统射中(因为不满足递减规律),因此至少得有这么套系统!    备注:由于思路是一样的,所以求最长非递减序列的元素个数的算法只给出非递归的形式!*/#include <iostream>#include<cstring>using namespace std;int digui(int h[],int i) /*递归法求解,函数返回的是dp[i]的值*/{    if(i==0)  /*如果就是第一个,说明它就单独是一类,因为它前面没有元素了*/        return 1; /*返回1*/    int max=0;  /*初始化max*/    for(int k=0;k<i;k++) /*从前面的所有元素中开始寻找*/      if(h[k]>h[i]&&max<digui(h,k))        max=digui(h,k);    return max+1;}void feidigui(int h[],int dp[],int n){    int max;    dp[0]=1;    for(int i=1;i<n;i++){        max=0;        for(int j=0;j<i;j++)            if(h[j]>h[i]&&max<dp[j])               max=dp[j];        dp[i]=max+1;    }}int digui_z(int h[],int i){    if(i==0)        return 1;    int max=0;    for(int k=0;k<i;k++)      if(h[k]<h[i]&&max<digui_z(h,k))        max=digui_z(h,k);    return max+1;}int main(){    int max,h[20],dp[20],n;    max=0;    memset(dp,0,sizeof(dp));    cout<<"请输入导弹的个数,这个数不要超过20!"<<endl;    cin>>n;    cout<<"请输入"<<n<<"个导弹的高度"<<endl;    for(int i=0;i<n;i++)        cin>>h[i];    feidigui(h,dp,n);    for(int i=0;i<n;i++)        if(max<dp[i])            max=dp[i];    cout<<"用非递归的方法求出的最多可以拦截的导弹数是"<<max<<"!"<<endl;    max=0;    for(int i=0;i<n;i++)        if(max<digui(h,i))            max=digui(h,i);    cout<<"用递归的方法求出的最多可以拦截的导弹数也是"<<max<<"!"<<endl;    max=0;    for(int i=0;i<n;i++)        if(max<digui_z(h,i))            max=digui_z(h,i);    cout<<"用递归的方法求出的至少需要的系统套数为"<<max<<"!"<<endl;    return 0;}