最长不降子序列——动态规划

本文介绍两种求解最长不降子序列的方法:动态规划算法和构造法,并提供C语言实现示例。动态规划通过记录每个位置上的最大子序列长度来逐步更新结果,构造法则通过维护一系列候选结尾值来高效解决问题。

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


2008-4-8

最长不降子序列
小明晚上回家后,和爸爸玩这样的一个游戏:给出N个 (0<N<1000)整数,从左到右取数,除的第一个数以外,每取一个数都要不比前一个取的数小。谁能取最多的数谁就胜出,获得巧克力一块。
输入:N个整数。
输出:最多能取多少个数。
样例输入:
4 1 2 3 1 5 6
样例输出:
5

一、 动态规划算法:

本题是比较简单的动态规划,请理解好递推的过程。具体方法是对于数组a[],另设一数组b[],将b[]数组内元素全置1, 表示最短子序列长度为1。从数组a[]左到右一个个判断,每判断一个,则从这个元素向右寻找,找到比它小的元素,查看比它小的元素对应的b[]里存的长度 值。然后加上1。这样一步步的推完。数组b[]中间最大的即为所求最长子序列的长度。

状态转移方程:b[i]=max{b[j]} +1  ,  0<=j<i。

#include<stdio.h>
#include<stdlib.h>
int a[]={3,2,7,6,8,5,3,4,5,9,1,3};
int b[]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int main()
{
    int i,j,max;
         for(i=0;i<12;i++)
         {
                max=0;
                for(j=0;j<=i-1;j++)
                {
                       if( a[i]>a[j] && max<b[j]+1 )
                            {
                            b[i]=b[j]+1;
                            max=b[i];
                            }         
                }
         }
  for(i=0;i<13;i++) printf("%d ",b[i]);
  system("pause");
}

b[]数组中最大的即为所求长度。

-------------------------------------------------------------------------

方 法二:构造法

算法伪代码:

算法---求数组a[]的最长不减子序列长
{
    置最长不减子序列长k为1;
    用a[0]设置长为1的子序列的终止元素;
    for(i=1;i<n;i++)        /*顺序至a[1]考察至a[n-1]*/
    {
        以子序列长为k至1的顺序寻找其终元素小于等于a[i]的长为j的子序列;
        用a[i]作为长为j+1的子序列的终元素;
        if(j==k)k++;        /*最长不减子序列长k增1*/
    }
}

例程:
#include<stdio.h>
int a[6]={3,2,1,5,9,7};
int b[100]={0};
int main()
{
    int i,j,k;
    k=1;
    b[1]=a[0];
    for(i=1;i<6;i++)
        {
        for(j=k;j>=1&&b[j]>a[i];j--);/*循环结束 ,J的指向*/
        b[j+1]=a[i];
        if(j==k)k++;
        }
    printf("k=%d",k);
    system("pause");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值