最长升序公共子序列 c语言,大家来看看这样的题:2000:最长公共子上升序列

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼

描述

给定两个整数序列,写一个程序求它们的最长上升公共子序列。

当以下条件满足的时候,我们将长度为N的序列S1 , S2 , . . . , SN 称为长度为M的序列A1 , A2 , . . . , AM 的上升子序列:

存在1 <= i1 < i2 < . . . < iN <= M ,使得对所有 1 <= j <=N,均有Sj = Aij,且对于所有的1 <= j < N,均有Sj < Sj+1。

输入

每个序列用两行表示,第一行是长度M(1 <= M <= 500),第二行是该序列的M个整数Ai (-231 <= Ai < 231 )

输出

在第一行,输出两个序列的最长上升公共子序列的长度L。在第二行,输出该子序列。如果有不止一个符合条件的子序列,则输出任何一个即可。

样例输入

51 4 2 5 -124-12 1 2 4

样例输出

21 4

题目分析

本题是典型的动态规划问题中的公共子序列问题的升级版本,在要求子序列的基础上又增加了递增的要求,这一要求使得原本的核心公式不再适用。

在本题的解决方案中,还是采用了一个二维数组作为动态规划表格,并留出每一行的第一列记录公共子序列长度,而每一行记录不同情况下的公共子序列。

算法过程为以s2为大循环,用s1的每一项与s2的第j项比较,s2[j]>s1[i]&&s[0]

两重循环完毕后,表格变为每行第一个为值为公共上升子序列长度,其后跟随该情况下的公共上升子序列。

数据结构

只用了一个二维数组,三个一位数组。

代码及算法说明

#include

#include

int s1[501],s2[501],t[501][501]={0},s[501];

int main()

{

int m,n,ans=0,i,j;

scanf("%d",&m);

for(i=1;i<=m;i++)scanf("%d",&s1[i]);

scanf("%d",&n);

for(i=1;i<=n;i++)scanf("%d",&s2[i]);

s1[0]=s2[0]=-99999; //尽可能小,确保后面判断。

for(j=1;j<=n;j++)

{

memset(s,0,sizeof(s)); //将s置零。

for(i=1;i<=m;i++)

{

if(s2[j]>s1[i]&&s[0]

memcpy(s,t[i],sizeof(t[i])); //将t[i]复制给s,即调出之前存储的公共上升子序列。

if(s1[i]==s2[j])

{

memcpy(t[i],s,sizeof(s)); //将s复制给t[i],即存储当前情况下子序列。

t[i][++t[i][0]]=s1[i]; //接上子序列,并计入长度+1。

}

}

}

for(i=1;i<=m;i++)

if(ans

printf("%d\n",ans);

for(i=1;i<=m;i++)

if(t[i][0]==ans)

{

for(j=1;j<=t[i][0];j++) printf("%d ",t[i][j]);

break;

}

return 0;

}

算法分析

1.该算法借鉴了网上的一些答案,之前没有看到要求递增,考虑之后发现大有不同,有些时候很容易被相似题目名称误导,耽误时间和精力。

2.使用了string.h中的memcpy()和memset()函数,使代码更加简洁。

3.本题还是采用了动态规划惯用的制作表格,但是其采用每一行的0位记录长度,并且核心制表代码精简巧妙,值得学习。

4.本代码中有许多小细节比较巧妙,利用简化代码和减少复杂度。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
1 引言 4 1.1 课程设计目标 4 1.2 编程工具(编程环境)介绍 4 1.3 实施时间及主要实施步骤 4 2 需求分析 5 3 系统总体设计 6 4 数据库设计 6 5 主要功能模块的设计与实现 10 5.1 功能模块1详细设计(综合查询员工信息)..........................................................10 5.1.1 详细设计.......................................................................................................10 5.1.2 算法流程........................................................................................................15 5.1.3 界面设计及测试结果.....................................................................................15 6 调试分析 15 7 用户手册 16 8 测试结果 17 8.1 员工信息的添加...................................................................................................17 8.2 员工信息的修改...................................................................................................17 8.3 员工信息的删除...................................................................................................18 8.4 员工信息的综合查询...........................................................................................18 8.5 员工信息按性别统计的结果................................................................................19 8.6 员工信息按状态统计的结果...............................................................................19 8.7 员工信息按职称统计的结果................................................................................20 9 结论 20 10 参考文献 20
©️2021 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值