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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最长合法序列

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;
}




<think>好的,用户想了解“单调”在数学或算法中的含义,特别是单调递增序列的意义。我需要先回顾一下相关概念,确保准确。 首先,数学中的单调性通常指函数或序列的变化趋势。比如单调递增就是每个后续项都不小于前一项。要区分严格和非严格的情况,比如严格递增是每个项都比前一个大,而非严格可能允许相等。 接下来在算法中的应用,比如最长递增子序列问题(LIS),动态规划是常见解法。这里需要引用提供的参考文献,比如引用[2]提到计算每个位置的最长子序列长度,引用[3]提到优化方法,保留不同长度的最小末尾元素,这可能涉及到贪心或二分优化。 还要注意用户提到的“单调递增序列”的具体应用,比如引用[4]中的贪心算法处理数字问题,确保数字每位单调递增。这里需要说明算法如何利用单调性来解决问题,比如调整数字位使其满足条件。 另外,用户可能对“单调”在不同上下文中的具体表现感兴趣。比如数学中的单调函数与算法中处理序列时的单调性有何异同,需要明确说明。 最后,确保回答结构清晰,分点解释数学定义和算法应用,并引用相关文献。同时生成的相关问题要围绕定义、区别、应用场景和优化方法展开,帮助用户进一步探索。</think>### 数学与算法中“单调”的定义及意义 #### 1. 数学中的单调性 在数学中,**单调性**描述的是序列或函数的变化趋势: - **单调递增**:对于序列$a_1, a_2, ..., a_n$,若满足$a_1 \leq a_2 \leq ... \leq a_n$,则称为**非严格单调递增**;若满足$a_1 < a_2 < ... < a_n$,则称为**严格单调递增**。 - **单调递减**:与递增类似,方向相反,即$a_1 \geq a_2 \geq ... \geq a_n$(非严格)或$a_1 > a_2 > ... > a_n$(严格)。 例如,序列$1,3,5,7$是严格递增的,而$1,3,3,5$是非严格递增的。 #### 2. 算法中的单调性应用 在算法领域,**单调序列**常用于优化问题和动态规划: - **最长递增子序列(LIS)**:要找到序列中满足单调递增条件的最长子序列。例如序列$1,2,3,5,8$是$1,2,3,5,8,6,5,3$的最长连续递增子序列[^5]。 - **动态规划解法**:通过比较前$n$项的最优解递推第$n+1$项的解[^2]。 - **优化方法**:保留每个长度下递增子序列的最小末尾元素,以降低时间复杂度[^3]。 - **贪心算法应用**:如“单调递增的数字”问题,通过调整数字位数确保整体单调性[^4]。 #### 3. 单调递增序列的意义 - **简化问题分析**:单调性可减少无效状态搜索,例如在动态规划中通过排除不可能产生最优解的子序列来提升效率[^3]。 - **约束条件**:在序列处理(如排序、数值调整)中,单调性常作为问题的核心约束条件,例如背包问题的最优子结构[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值