当前位置: 首页 > article >正文

算法学习系列(三十三):线性DP

目录

  • 引言
  • 一、数字三角形
  • 二、最长上升子序列
  • 三、最长公共子序列

引言

这个线性DP其实也就是一种描述吧,有的是一维、二维、多维的,就是这个动规方程是按顺序来的,所以叫做线性,然后还是得按题目来看,把每种题都见过才能有思路,才会写,DP其实没啥思想规范,就是做题见题,才会做题。


一、数字三角形

思路:把这个三角形看成二维的,横着的代表行,斜着的代表列,则 f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j − 1 ] , f [ i − 1 ] [ j ] ) + a [ i ] [ j ] f[i][j]=max(f[i-1][j-1],f[i-1][j])+a[i][j] f[i][j]=max(f[i1][j1],f[i1][j])+a[i][j]

题目描述:

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,
要求找出一条路径,使路径上的数字的和最大。

        7
      3   8
    8   1   0
  2   7   4   4
4   5   2   6   5

输入格式
第一行包含整数 n,表示数字三角形的层数。

接下来 n 行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。

输出格式
输出一个整数,表示最大的路径数字和。

数据范围
1≤n≤500,−10000≤三角形中的整数≤10000
输入样例:
5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5
输出样例:
30

示例代码:

#include <cstdio>
#include <iostream>

using namespace std;

const int N = 510, INF = 1e9;

int n;
int a[N][N];
int f[N][N];

int main()
{
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= i; ++j)
        {
            cin >> a[i][j];
        }
    }
    
    for(int i = 0; i <= n; ++i)  //因为会有负数,所以初始化为最小值
    {
        for(int j = 0; j <= n; ++j)
        {
            f[i][j] = -INF;
        }
    }
    
    f[1][1] = a[1][1];
    for(int i = 2; i <= n; ++i)
    {
        for(int j = 1; j <= i; ++j)
        {
            f[i][j] = max(f[i-1][j-1], f[i-1][j]) + a[i][j];
        }
    }
    
    int res = -INF;
    for(int i = 1; i <= n; ++i) res = max(res, f[n][i]);
    
    cout << res << endl;
    
    return 0;
}

二、最长上升子序列

思路: f [ i ] f[i] f[i] 代表以 i i i 为结尾的最长递增子序列最长长度,每个 i i i 中,判断之前小于 a [ i ] a[i] a[i] 的中的最长是多少,在加上自己,如果没有不小于 a [ i ] a[i] a[i] 的,则 f [ i ] f[i] f[i] 就为1(只有自己)

题目描述:

给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。

输入格式
第一行包含整数 N。

第二行包含 N 个整数,表示完整序列。

输出格式
输出一个整数,表示最大长度。

数据范围
1≤N≤1000,−109≤数列中的数≤109
输入样例:
7
3 1 2 1 8 5 6
输出样例:
4

示例代码:

#include <cstdio>
#include <iostream>

using namespace std;

const int N = 1010;

int n;
int a[N];
int f[N];

int main()
{
    cin >> n;
    for(int i = 1; i <= n; ++i) cin >> a[i];
    
    for(int i = 1; i <= n; ++i)
    {
        f[i] = 1;
        for(int j = 1; j < i; ++j)
        {
            if(a[i] > a[j]) f[i] = max(f[i], f[j] + 1);
        }
    }
    
    int res = 0;
    for(int i = 1; i <= n; ++i) res = max(res, f[i]);
    
    cout << res << endl;
    
    return 0;
}

三、最长公共子序列

思路:f[i][j]代表A串前i个字母和B串前j个字母的最长序列,f[i][j]可以划分为a[i] b[j]都不选,当前选a[i]不选b[j]中的,选b[j]不选a[i],两个都选,也就是f[i-1][j-1] f[i][j-1] f[i-1][j] f[i-1][j-1]+1,但是选A串中的不选B中的,其实不等于f[i][j-1],这只说明前i个和前j-1个中的最长,没有说一定选a[i],但因为我们求的是最大值,而f[i][j-1] 一定是包含要的这种情况的,而且f[i][j-1]的最大情况也就是选a[i]不选b[j]这种情况的,所以虽然不等于但求最大值结果是一样的,f[i-1][j]也是等价的,同理f[i-1][j] 也是包含f[i-1][j-1]这种情况的,所以从三个里面取最大值就行了。

题目描述:

给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。

输入格式
第一行包含两个整数 N 和 M。

第二行包含一个长度为 N 的字符串,表示字符串 A。

第三行包含一个长度为 M 的字符串,表示字符串 B。

字符串均由小写字母构成。

输出格式
输出一个整数,表示最大长度。

数据范围
1≤N,M≤1000
输入样例:
4 5
acbd
abedc
输出样例:
3

示例代码:

#include <cstdio>
#include <iostream>

using namespace std;

const int N = 1010;

int n, m;
char a[N], b[N];
int f[N][N];

int main()
{
    cin >> n >> m;
    cin >> a+1 >> b+1;
    
    for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= m; ++j)
        {
            f[i][j] = max(f[i-1][j], f[i][j-1]);
            if(a[i] == b[j]) f[i][j] = max(f[i][j], f[i-1][j-1] + 1);
        }
    }
    
    cout << f[n][m] << endl;
    
    return 0;
}

http://www.kler.cn/a/232253.html

相关文章:

  • Python学习从0到1 day29 Python 高阶技巧 ⑦ 正则表达式
  • Ubuntu 18 EDK2 环境编译
  • 【网络安全 | 甲方建设】双/多因素认证、TOTP原理及实现
  • Elastic Agent:可灵活地在任何地方发送和处理任何数据
  • redis linux 安装
  • c#————委托Action使用例子
  • Golang 学习(二)进阶使用
  • Java排序方法
  • 桌面显示器应用Type-C接口有什么好处
  • 人工智能专题:量子汇编语言和量子中间表示发展白皮书
  • python烟花绘制,春节祝福
  • React 组件跨层级数据共享:createContext、useContext、useMemo
  • Compose | UI组件(十四) | Navigation-Data - 页面导航传递数据
  • OpenHarmony轻量级驱动开发
  • Linux笔记之expect和bash脚本监听输出并在匹配到指定字符串时发送中断信号
  • string容器
  • ubuntu原始套接字多线程负载均衡
  • 【芯片设计- RTL 数字逻辑设计入门 15 -- 函数实现数据大小端转换】
  • 分布式系统架构介绍
  • Kafka系列之:Kafka集群同时设置基于时间和日志大小两种方式保存Topic的数据
  • [当人工智能遇上安全] 11.威胁情报实体识别 (2)基于BiGRU-CRF的中文实体识别万字详解
  • ubuntu22.04@laptop OpenCV Get Started: 002_reading_writing_videos
  • 【龙年大礼】| 2023中国开源年度报告!
  • 大模型2024规模化场景涌现,加速云计算走出第二增长曲线
  • 从Unity到Three.js(安装启动)
  • STM32输出PWM波控制180°舵机