pta求阶乘序列前n项和_2000:最长公共子上升序列 【动态规划之子序列】

本文介绍了一种求解两个整数序列的最长公共子上升序列的算法,通过使用向量存储序列,并结合动态规划的方法,实现了高效求解。

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

b34f1d215207b78e4d3b3ad8f1b75718.png

by Oler 87

姓名:庄宇浩 学号:087

2000:最长公共子上升序列

总时间限制: 10000ms

内存限制: 65536kB

描述

给定两个整数序列,写一个程序求它们的最长上升公共子序列。
当以下条件满足的时候,我们将长度为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个整数(-231 <= Ai < 231 )输出

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

5

1 4 2 5 -12

4

-12 1 2 4

样例输出

2

1 4

题目分析

相较于典型的求最长子序列和求上升子序列问题,这道题综合了两道题的特点,需要求两个zx序列的最长公共子序列,具有更高的难度,也需要用升级版的DP算法解决.

这道题用向量解法很轻松.首先,程序中定义了一个结构体,其中包括一个整形向量w和向量中的元素个数val(初始值为零).然后输入两个数组a[501]和b[501],然后定义一个向量Max为最长公共子序列结构体.dp[501]作为交换值,作为中间变量.

关键是比较部分.比较部分基于b[i]在外,ap[j]在内的双重循环.if (b[i] > a[j] && dp[j].val > Max.val):如果b[i]大于a[j]而且dp结构体中的向量个数大于Max中的向量元素个数,就把dp[j]赋值给Max.

if (b[i] == a[j]):如果b[i]等于a[j],就把b[i]补到dp[j]向量的尾部,并且结构体中对应的元素个数加一.

最后是输出部分.开始把dp[1]赋值给Max,然后进行循环比较.一直比到dp[501],比出最大的那个,然后将其输出.

数据结构

两个一维整形数组,一个结构体数组,一个结构体变量.

代码及算法说明

#include<vector>

#include<iostream>

using namespace std;

struct Node { //定义结构体

int val = 0; //val指向量中含有的元素个数

vector<int>w; //指该向量为一维整形向量

};

int main() {

int a[501], b[501]; //两个比较数组

Node dp[501]; //记录公共子序列的中间值

int m, n; //数组中元素的个数

cin >> m; //cin函数相当于c语言中的scanf函数

for (int j = 1; j <= m; j++)

cin >> a[j];

cin >> n;

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

cin >> b[j];

for (int i = 1; i <= n; i++)

{

Node Max; //max即为最长公共子序列

for (int j = 1; j <= m; j++) {

if (b[i] > a[j] && dp[j].val > Max.val) //判断条件:后一个数组元素值大于前一个并且对应数组元素个数比前一个多

Max = dp[j]; //将max赋值给元素个数更多的那个

if (b[i] == a[j]) {

dp[j].val = Max.val + 1;

dp[j].w = Max.w; //如果b[i] == a[j],则把b[i]补到dp[j]向量的尾部

dp[j].w.push_back(b[i]);

}

}

}

Node Max = dp[1]; //开始把max赋值给dp[1]

for (int i = 2; i <= m; i++) {

if (dp[i].val > Max.val) //对所有dp元素中的元素个数进行比较,并将max赋值给元素个数最多的那个

Max = dp[i];

}

cout << Max.val << endl;

for (int i = 0; i < Max.w.size(); i++)

cout << Max.w[i] << " "; //输出结构体max

cout << endl;

return 0;

}

算法分析

1.该算法有一部分参考了网上答案,其中的比较部分觉得很精炼,但是后来想了下觉得跟普通的比较算法差不多,注意要用向量的话要在头文件里加上#include<vector>

2.相较于数组,向量的优点在于:向量比较灵活,可以对向量中的元素进行添加和删除,能够有效的避免越界问题.而且对向量进行的函数操作更加方便.比如插入元素在 向量 中 只需要push_back函数,而在数组中则要用循环来赋值.

3.本代码中有许多细节很巧妙,比较部分可以大大减少代码长度,值得好好琢磨,并加以学习.

4.有不足之处们还请同学批评指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值