Acwing-基础算法课笔记之动态规划(线性DP)

Acwing-基础算法课笔记之动态规划(线性DP)

  • 一、数字三角形
    • 1、概述
    • 2、闫氏dp分析法
    • 代码示例
  • 二、最长上升子序列
    • 1、概述
    • 2、闫氏dp分析法
    • 3、过程模拟
    • 4、代码演示
  • 三、最长上升子序列强化版
    • 1、概述
    • 2、代码示例
  • 四、最长公共子序列(LCS)
    • 1、定义
      • (1)分解
      • (2)子问题
    • 2、过程模拟
    • 3、代码示例
  • 五、最短编辑距离
    • 1、定义
      • (1)分解
      • (2)子问题
    • 2、过程模拟
    • 3、代码示例

一、数字三角形

1、概述

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

2、闫氏dp分析法

在这里插入图片描述
在这里插入图片描述

代码示例

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 510;
int n;
int dp[N][N], w[N][N];
int main() {scanf("%d", &n);for (int i = 1; i <= n; i++) {for (int j = 1; j <= i; j++) {scanf("%d", &w[i][j]);}}for (int i = 1; i <= n; i++)dp[n][i] = w[n][i];//因为从底部开始往上寻找,所以将底部的dp先初始化for (int i = n - 1; i >= 1; i--) {for (int j = 1; j <= i; j++) {dp[i][j] = max(dp[i + 1][j] + w[i][j], dp[i + 1][j + 1] + w[i][j]);}}printf("%d", dp[1][1]);return 0;
}

二、最长上升子序列

1、概述

给定一个长度为N的数列A,求数量单调递增的子序列的长度最长是多少。A的任意子序列B可表示为 B = { A k 1 , A k 2 , . . . , A k p } B=\{A_{k_1},A_{k_2},...,A_{k_p}\} B={Ak1,Ak2,...,Akp},其中 k 1 < k 2 < ⋯ < k p k_1<k_2<\cdots<k_p k1<k2<<kp

2、闫氏dp分析法

在这里插入图片描述

3、过程模拟

如何理解所有以第i个数结尾的上升子序列
在这里插入图片描述
例如: 8 8 8为第 i i i个数,则 8 8 8前面的上升子序列为:
3 , 8 3,8 3,8
1 , 8 1,8 1,8
2 , 8 2,8 2,8
1 , 2 , 8 1,2,8 1,2,8

4、代码演示

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n;
int a[N], dp[N];
int main() {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);}for (int i = 1; i <= n; i++) {dp[i] = 1;for (int j = 1; j <= i; j++) {if (a[j] < a[i]) {dp[i] = max(dp[i], dp[j] + 1);}}}int ans = 0;for (int i = 1; i <= n; i++) {ans = max(ans, dp[i]);}printf("%d", ans);return 0;
}

三、最长上升子序列强化版

1、概述

由于数据范围比较大,所以只能利用二分的思想先筛选出序列中最大的数,找出该数前的最大上升子序列。

2、代码示例

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N], dp[N];
int main() {scanf("%d", &n);for (int i = 0; i < n; i++)scanf("%d", &a[i]);int len = 0;dp[0] = -2e9;for (int i = 0; i < n; i++) {int l = 0, r = len;while (l < r) {int mid = l + r + 1 >> 1;if (dp[mid] < a[i])l = mid;else r = mid - 1;}len = max(len, r + 1);dp[r + 1] = a[i];}printf("%d", len);return 0;
}

四、最长公共子序列(LCS)

1、定义

例如:
s 1 : A B C B D A B s_1:ABCBDAB s1:ABCBDAB
s 2 : B D C A B C s_2:BDCABC s2:BDCABC
D [ i ] [ j ] = s 1 D[i][j]=s_1 D[i][j]=s1 i i i个字符与 s 2 s_2 s2 j j j个字符的 L C S LCS LCS
例如: D [ 7 ] [ 6 ] = 4 D[7][6]=4 D[7][6]=4

(1)分解

1、 D [ i ] [ j ] = D [ i − 1 ] [ j − 1 ] + 1 D[i][j]=D[i-1][j-1]+1 D[i][j]=D[i1][j1]+1
2、 D [ i ] [ j ] = m a x ( D [ i − 1 ] [ j ] D [ i ] [ j − 1 ] ) D[i][j]=max\begin{pmatrix} D[i-1][j] \\ D[i][j-1] \end{pmatrix} D[i][j]=max(D[i1][j]D[i][j1])

(2)子问题

D 00 = 0 , D i 0 = 0 , D 0 j = 0 D_{00}=0,D_{i0}=0,D_{0j}=0 D00=0,Di0=0,D0j=0

2、过程模拟

在这里插入图片描述
⋇ \divideontimes 如果两个字符串的末尾字符相同,分析如下:

∙ \bullet D [ i ] [ j ] = D [ i − 1 ] [ j − 1 ] + 1 D[i][j]=D[i-1][j-1]+1 D[i][j]=D[i1][j1]+1

⋇ \divideontimes 如果两个字符串的末尾字符不同需要舍弃两字符串中的其中一个末尾的字符 x x x y y y,分析如下:

∙ \bullet 如果舍弃 s 1 s_1 s1 x x x,则 D [ i ] [ j ] = m a x ( D [ i − 1 ] [ j ] ) D[i][j]=max(D[i-1][j]) D[i][j]=max(D[i1][j])

∙ \bullet 如果舍弃 s 2 s_2 s2 y y y,则 D [ i ] [ j ] = m a x ( D [ i ] [ j − 1 ] ) D[i][j]=max(D[i][j-1]) D[i][j]=max(D[i][j1])

画表格来描述:

1、 D [ i ] [ j ] = D [ i − 1 ] [ j − 1 ] + 1 , s 1 [ i − 1 ] = s 2 [ j − 1 ] D[i][j]=D[i-1][j-1]+1,s_1[i-1]=s_2[j-1] D[i][j]=D[i1][j1]+1,s1[i1]=s2[j1]
2、 D [ i ] [ j ] = m a x ( D [ i − 1 ] [ j ] D [ i ] [ j − 1 ] ) , s 1 [ i − 1 ] ! = s 2 [ j − 1 ] D[i][j]=max\begin{pmatrix} D[i-1][j] \\ D[i][j-1] \end{pmatrix},s_1[i-1]!=s_2[j-1] D[i][j]=max(D[i1][j]D[i][j1]),s1[i1]!=s2[j1]

∅ \varnothing BDCABC
∅ \varnothing 0000000
A0
B0
C0
B0
D0
A0
B0

⇓ \Darr

∅ \varnothing BDCABC
∅ \varnothing 0000000
A0000111
B0111122
C0112223
B0112233
D0122233
A0122333
B0122344

方法: 看坐标 ( i , j ) (i,j) (i,j)的元素是否相等,如果相等则以左斜上方的数为基础加 1 1 1,否则等于左边的数。

如果不理解可以看一看这位大佬的视频

3、代码示例

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n, m;
int dp[N][N];
char a[N], b[N];
int main() {cin >> n >> m;cin >> a + 1;cin >> b + 1;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {if (a[i] == b[j])dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}}cout << dp[n][m];return 0;
}

五、最短编辑距离

1、定义

D [ i ] [ j ] D[i][j] D[i][j]等于 s 1 s_1 s1 i i i个字符编辑为 s 2 s_2 s2的前 j j j个字符它的编辑距离。
例如:
s u n sun sun编辑为 s a t u r satur satur,则 D 35 = 3 D_{35}=3 D35=3

(1)分解

⋇ \divideontimes 如果 s 1 s_1 s1 s 2 s_2 s2的末尾字符相同,则只要编辑 s i − 1 s_{i-1} si1的字符串变成 s j − 1 s_{j-1} sj1的字符串的次数
在这里插入图片描述
∙ \bullet 如果 s i − 1 s_{i-1} si1等于 s j − 1 s_{j-1} sj1,则 D [ i ] [ j ] = D [ i − 1 ] [ j − 1 ] D[i][j]=D[i-1][j-1] D[i][j]=D[i1][j1]

⋇ \divideontimes 如果 s 1 s_1 s1 s 2 s_2 s2的末尾字符不相同
在这里插入图片描述
∙ \bullet 如果 s 1 s_1 s1的字符串末尾与 s 2 s_2 s2相比少了一个 y y y,则在 s 1 s_1 s1的末尾插入 y y y,则状态转移方程为: D [ i ] [ j ] = D [ i ] [ j − 1 ] + 1 D[i][j]=D[i][j-1]+1 D[i][j]=D[i][j1]+1

∙ \bullet 如果 s 1 s_1 s1的字符串末尾与 s 2 s_2 s2相比多了一个 x x x,则删除 s 1 s_1 s1末尾的 x x x,则状态转移方程为: D [ i ] [ j ] = D [ i − 1 ] [ j ] + 1 D[i][j]=D[i-1][j]+1 D[i][j]=D[i1][j]+1

∙ \bullet 如果 s 1 s_1 s1 s 2 s_2 s2具有高度的相似性,则将 s 1 s_1 s1当中的某个字符替换成 s 2 s_2 s2当中的某个字符,则状态转移方程为: D [ i ] [ j ] = D [ i − 1 ] [ j − 1 ] + 1 D[i][j]=D[i-1][j-1]+1 D[i][j]=D[i1][j1]+1

在这三种条件中选最小

(2)子问题

D 00 = 0 , D i 0 = i , D 0 j = j D_{00}=0,D_{i0}=i,D_{0j}=j D00=0,Di0=i,D0j=j

2、过程模拟

在这里插入图片描述

∅ \varnothing satur
∅ \varnothing 012345
s1
u2
n3

⇓ \Darr

∅ \varnothing satur
∅ \varnothing 012345
s101234
u211223
n322233

方法: 如果所在同一坐标的两个字符相等,则该坐标的值等于左上方坐标的值。如果不相等,则需要考虑是插入、删除还是替换。如果是插入,则当前坐标的值等于左边坐标的值加 1 1 1。如果是删除,则当前坐标的值等于上方的值加 1 1 1。如果是替换,则当前坐标的值等于左上方的值加 1 1 1

3、代码示例

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1010;
int n, m;
char a[N], b[N];
int dp[N][N];
int main() {scanf("%d%s", &n, a + 1);scanf("%d%s", &m, b + 1);for (int i = 1; i <= n; i++)dp[i][0] = i;for (int j = 1; j <= m; j++)dp[0][j] = j;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {dp[i][j] = min(dp[i][j - 1] + 1, dp[i - 1][j] + 1);if (a[i] == b[j])dp[i][j] = min(dp[i][j], dp[i - 1][j - 1]);else dp[i][j] = min(dp[i - 1][j - 1] + 1, dp[i][j]);}}printf("%d\n", dp[n][m]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/754117.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

你开发的系统国际化了吗?

亲爱的朋友们&#xff0c;周一好&#xff0c;新的一周&#xff0c;精神满满。 在开发Spring Boot应用时&#xff0c;接口的参数校验是一个重要的环节&#xff0c;它确保了数据的完整性和准确性。而国际化处理则使得应用能够支持多种语言&#xff0c;提升了用户体验。 一、参数…

ev多域名ssl证书2000元一年送一月

多域名SSL证书是一种特殊的数字证书产品。多域名SSL证书可以同时保护多个独立的域名站点&#xff0c;这些域名站点可以是多个主域名、子域名&#xff0c;多域名SSL证书可以为它们提供传输数据加密服务以及身份认证服务。EV多域名SSL证书具有更高的安全性&#xff0c;所以一些金…

深入了解主播美颜技术:从美颜SDK到实时美颜算法

在当今数字化时代&#xff0c;直播行业蓬勃发展&#xff0c;成为了人们日常生活中不可或缺的一部分。而在直播中&#xff0c;主播的形象对于吸引观众、提升观看体验至关重要。为了呈现更加美好的形象&#xff0c;主播们常常会借助美颜技术。从最初的美颜SDK到如今的实时美颜算法…

PS学习-对象选择抠图,覆盖

之前使用通道抠图抠大树 对象 选择 ctrlj 水平居中 选区羽化 选择加选按住shift&#xff0c;减选按住alt 单个选择按住shift是变正方形&#xff0c;或者椭圆变成圆 覆盖 想把天空都变成白色 选区羽化ctrlj 复制粘贴几个往上放 复制了十来个&#xff0c;遮住就行 首先存储为PS…

二叉搜索树题目:将有序链表转换为二叉搜索树

文章目录 题目标题和出处难度题目描述要求示例数据范围 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;将有序链表转换为二叉搜索树 出处&#xff1a;109. 将有序链表转换为二叉搜索树 难度 5 级 题目描述 要求 …

SPA单页面有哪些优缺点

单页面应用&#xff08;SPA&#xff09;作为一种现代化的Web应用程序架构&#xff0c;在当今互联网时代越来越受到开发者和用户的欢迎。它通过在加载应用程序时只加载一次页面&#xff0c;实现页面内容的动态更新&#xff0c;带来了许多优势和挑战。本文将深入探讨SPA的优点和缺…

【kaggle竞赛】从手写图像数据集中正确识别数字

1. 题目&#xff1a; 在本次比赛中&#xff0c;您的目标是从数以万计的手写图像数据集中正确识别数字。 1.1. Goal 目标✨ 本次比赛的目标是拍摄手写个位数的图像&#xff0c;并确定该数字是什么。 对于测试集中的每个标签&#xff0c;您都应该预测正确的标签。 本次比赛的…

SpringCloudLoadBalancer入门与实战系列

目录 一、什么是LoadBalancer&#xff1f; 1.1 负载均衡的分类 1.2 负载均衡策略 二、 为什么要学习 Spring Cloud Balancer &#xff1f; 三、 Spring Cloud LoadBalancer 内置的两种负载均衡策略 3.1 轮询负载均衡策略&#xff08;默认的&#xff09; 3.2 随机负载均衡…

科研学习|研究方法——案例研究方法

目录 1.案例研究的起源 2.案例研究的说服力 2.1 外界质疑 2.1.1 样本数量太小 2.1.2 选择的样本带有偏倚 2.1.3 选择的案例太少 2.1.4 无法验证 2.2 重要作用 2.2.1 激发研究 2.2.2 启发灵感 2.2.3 提供佐证 3.案例研究的内容 4.案例研究质量的评价 5.案例研究的优缺点 6.MI…

wsl or 虚拟机 安装

1.wsl2安装 WSL全称Windows Subsystem for Linux&#xff0c;是微软开发的适用于Linux的Windows子系统 如今已经有两代了&#xff1a; 所以用的多的还是wsl2。 安装前需要先去设置启用或关闭Windows功能&#xff1a; 打开适用于linux的子系统和虚拟机平台。 Microsoft Store里…

【实验01 扩展实验】C#桌面项目:简易计算器

【实验要求】 &#xff08;1&#xff09;新建一个C#桌面项目Calc&#xff0c;实现简易计算器功能&#xff0c;界面如图1所示。 &#xff08;2&#xff09;计算方式&#xff1a;通过点击对应的按钮&#xff0c;输入第1个数&#xff08;可以是整数或实数&#xff09;&#xff0c…

微服务:高并发带来的问题的容错方案

1.相关脚本&#xff08;陈天狼&#xff09; 启动nacos客户端&#xff1a; startup.cmd -m standalone 启动sentinel控制台&#xff1a; # 直接使⽤jar命令启动项⽬(控制台本身是⼀个SpringBoot项⽬) java -Dserver.port8080 -Dcsp.sentinel.dashboard.serverlocalhost:808…

【复现】【免费】基于多时间尺度滚动优化的多能源微网双层调度模型

目录 主要内容 部分代码 结果一览 1.原文结果 2.程序运行结果 下载链接 主要内容 该模型参考《Collaborative Autonomous Optimization of Interconnected Multi-Energy Systems with Two-Stage Transactive Control Framework》&#xff0c;主要解决的是一个…

03|提示工程(下):用思维链和思维树提升模型思考质量

什么是 Chain of Thought CoT这个概念来源于学术界&#xff0c;是谷歌大脑的Jason Wei等人于2022年在论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models&#xff08;自我一致性提升了语言模型中的思维链推理能力&#xff09;》中提出来的概念。它…

2024-Spring IOC 和 AOP源码分析(上篇)

**前言&#xff1a;**笔者最近面了几次大厂。。。开局Spring源码暴击 之前看过忘了写篇总结。。。 1、介绍一下Spring 核心组件&#xff1a; 常用模块&#xff1a; 常用注解&#xff1a; 2、说一下SpringIOC原理 概念&#xff1a;Spring 通过一个配置文件描述 Bean 及 B…

【Godot4自学手册】第二十六节用GPUParticles2D节点实现地宫入口的奇异光芒

我们的主人公与NPC对话完成后&#xff0c;夜晚来临&#xff0c;在城北有一处乱石岗&#xff0c;出现了奇异光芒&#xff0c;这是地宫的入口&#xff0c;但是有一妖怪把守&#xff0c;我们必须消灭妖怪后才可发现地宫入口。这一节&#xff0c;主要记录利用粒子系统GPUParticles2…

Python和R的区别是什么,Python与R的应用场景是什么?

如果你这么问&#xff0c;那么你可能正站在数据科学的起点。对于志在成为数据专业人员的你来说&#xff0c;学习编程是无疑的。我想行你早就听过Python 与R的比较之声&#xff0c;并在选择中感到困惑。在此&#xff0c;我想说&#xff0c;也算是一种安慰吧&#xff1a;对于语言…

TypeScript:typescript的安装与运行

TypeScript&#xff1a;typescript的安装与运行 1 安装方式 -g全局安装TypeScript&#xff1a; npm install -g typescript2 运行方式 &#xff08;1&#xff09;ts编译成js&#xff0c;使用node命令运行js文件 打开vscode&#xff0c;进入ts文件所在目录下并打开终端term…

【算法】多路归并(鱼塘钓鱼)

有 N 个鱼塘排成一排&#xff0c;每个鱼塘中有一定数量的鱼&#xff0c;例如&#xff1a;N5 时&#xff0c;如下表&#xff1a; 鱼塘编号12345第1分钟能钓到的鱼的数量&#xff08;1..1000&#xff09;101420169每钓鱼1分钟钓鱼数的减少量&#xff08;1..100)24653当前鱼塘到下…

静态综合实验

一&#xff0c;1.搭建拓扑结构并启动。 2.根据题意得该图需要14个网段&#xff0c;根据192.168.1.0/24划分子网段&#xff0c;如下&#xff1a; 划分完如图所示&#xff1a; 二、配置IP地址 R1路由器&#xff1a; 1.进入系统视图并改名. 2.接口配置IP地址&#xff1a…