应用递推的方法求最长非递减子序列的长度

该程序采用递归方法解决给定整数序列中找到最长的非递减子序列的问题。首先读取序列长度和整数,然后通过动态规划计算每个位置处最长子序列的长度及前一个元素的位置。最后,输出最长子序列的长度及其序列本身。

最长合法序列

Time Limit:1000MS  Memory Limit:65536K
Total Submit:55 Accepted:4

Description

有k个整数A[1],A[2]…A[k](0 < a[i] <= 2000000000, 0 < i <= k, 0 < k <= 1000,),你需要从前往后选出若干数,
使得每一个后面的数都要大于或等于前面的数。例如,对于序列1,4,2,5,2,3,选出1,2,2,3是合法的,但是选出4,2,3是不合法的。
请你编写程序对于一个已知序列,求出最长的合法序列的数的个数。


Input

每组测试数据由两行组成:

第一行为整数k,表示k个整数;
第二行有k个数A[1],A[2]….A[k]。

测试数据以0做为结束标志


Output

输出2*n行,先输出一个整数,表示相应测试序列中最长的合法序列的数的个数。

再输出一行表示最长合法序列是什么


Sample Input

12
13 45 23 53 23 88 123 3 125 10 87 89
6
1 4 2 5 2 3
0


Sample Output

6
13 ,45 ,53 ,88 ,123 ,125
4
1 ,2 ,2 ,3


代码如下:

#include <iostream>
#include <fstream>

using namespace std;


int maxValue(int a[],int len[],int n)
{//求a数组的前n元素中<=a[n]的最长子序列的长度

     int j=-1,maxlen=0;
     for(int i=0;i<n;i++)
     {
         if(a[i]<=a[n] && len[i]>maxlen)
         {
             j=i;maxlen=len[i];
         }     
     }    
     return j;//len[j]是最长子序列的长度
}     

void ress(int a[],int path[],int i)
{//利用递归输出最长合法子序列(最长非递减子序列)
    if(path[i]!=-1)
    {
        ress(a,path,path[i]);
        cout<<" ,"<<a[i];
    }  
    else
     cout<<a[i];  
}    
int main(int argc, char *argv[])
{
  int i;
  int n;
  int *a,*len,*path;   //a数组存储一组测试数据的n个整数

                                  //len[i]存储a[0]~a[i]序列中最长子序列的长度

                                 //path[i]存储最长合法子序列中a[i]的前一个整数的位置(下标)

  while(1)
  {
      cin>>n;
      if(n==0) break;
      
      a=new int[n];
      len=new int[n];
      path=new int[n];
     
      for(i=0;i<n;i++)   
      {
          cin>>a[i];
          if(i==0) {  //初始化
              len[i]=1;
              path[i]=-1;
          }    
          else
          {
              int j=maxValue(a,len,i);
              if(j==-1) {
                  len[i]=1;
                  path[i]=-1;
              }
              else{
                  len[i]=len[j]+1;
                  path[i]=j;
              }        
          }    
      }  
      int maxlen=0,maxi=0;
      for(int j=0;j<n;j++)
      {
          if(len[j]>maxlen) {
              maxlen=len[j];
              maxi=j;
          }
      }    
      
      cout<<maxlen<<endl;
      ress(a,path,maxi,cout);
      cout<<endl;
      delete [] a;
      delete [] len;
      delete [] path;
    
  }    
 
  system("PAUSE");    
  return 0;
}




评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值