Java实现动态规划经典题目

article/2025/10/7 3:43:35

动态规划入门请看:
DP动态规划专题(一)动态规划基本模型

前言

【说明】

关于动态规划的见解:动规和递归有很多相似的地方,最显著的特征可以说是阶段性,二者都有很明显的阶段划分,所以,声明好每一个阶段所需要做的事情以及阶段与阶段之间的转移可以说是重中之重了,这就涉及几个问题,第一,需要声明好方法(递归)或者数组(动规)具体的意义,所代表的作用;第二,需要说明好递归处理数据的方式(递归)或者是阶段转移方程(动规)。第三,跳出方法的条件(递归)或者是数组边界条件(动规)。处理好这三个方面,基本上就没有问题,剩下的就是一些边边角角的问题。

【提炼】

  • 声明数组代表的含义
  • 状态转移方程
  • 边界条件

代码

1.数字金字塔

【题目】

观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。

在这里插入图片描述

在上面的样例中,从13到8到26到15到24的路径产生了最大的和86。
【输入】:
第一个行包含R(1<= R<=1000),表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
所有的被供应的整数是非负的且不大于100。
【输出】:
单独的一行,包含那个可能得到的最大的和。
【样例输入】:
5 //数塔层数
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11
【样例输出】:
86

【代码1】

	/*** 顺推 dp* 含义:f[x][y] 从0,0到x,y最大值* 方程:f[x][y] = max{f[x-1][y],f[x-1][y-1]} + a[x][y]* 边界:f[0][0] = a[0][0]* */public int positive(int[][] a) {int[][] f = new int[a.length][a.length];// 边界f[0][0] = a[0][0];// 状态转移方程int i,j;for (i=1; i<a.length; i++) {for (j=0; j<=i; j++) {/*判断是否数组越界,左右两边需单独处理*/if (j == 0) {f[i][j] = f[i-1][j] + a[i][j];} else if (j == i) {f[i][j] = f[i-1][j-1] + a[i][j];} else {int max = f[i-1][j] > f[i-1][j-1] ? f[i-1][j] : f[i-1][j-1];f[i][j] = max + a[i][j];}}}// 获取最大值int temp = 0;for (i=0; i<a.length; i++) {if (f[a.length-1][i] > temp) {temp = f[a.length-1][i];}}return temp;}

【代码2】

	/*** 逆推* 含义:f[x][y]表示从x,y到终点的最大值,所以f[0][0]即为所求* 公式:f[x][y] = max{f[x+1][y+1],f[x+1][y]} + a[x][y]* 边界:f[length-1][0...length-1] = a[length-1][0...length-1]* */public int negative(int[][] a) {int[][] f = new int[a.length][a.length];// 边界int i,j;for (i=0; i<a.length; i++) {f[a.length-1][i] = a[a.length-1][i];}// 状态转移for (i=a.length-2; i>=0; i--) {for (j=0; j<=i; j++) {int max = f[i+1][j+1] > f[i+1][j] ? f[i+1][j+1] : f[i+1][j];f[i][j] = max + a[i][j];}}return f[0][0];}

2.最长不下降子序列
㈠问题描述:

设有由n个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)且b(i)<>b(j) (i<>j),若存在i1<i2<i3< … < ie 且有b(i1)<b(i2)< … <b(ie)则称为长度为e的不下降序列。程序要求,当原数列出之后,求出最长的不下降序列。

  • 例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。
  • 例中13,16,18,19,21,22,63就是一个长度为7的不下降序列,
  • 同时也有7 ,9,16,18,19,21,22,63长度为8的不下降序列。

㈡算法分析:
根据动态规划的原理,由后往前进行搜索(当然从前往后也一样)。

  1. 对b(n)来说,由于它是最后一个数,所以当从b(n)开始查找时,只存在长度为1的不下降序列;
  2. 若从b(n-1)开始查找,则存在下面的两种可能性:
    ①若b(n-1)<b(n)则存在长度为2的不下降序列b(n-1),b(n)。
    ②若b(n-1)>b(n)则存在长度为1的不下降序列b(n-1)或b(n)。
  3. 一般若从b(i)开始,此时最长不下降序列应该按下列方法求出:
    在b(i+1),b(i+2),…,b(n)中,找出一个比b(i)大的且最长的不下降序列,作为它的后继。

㈢代码:

public class LongSubSequence {/*** 最长不下降子序列* 逆序* 含义:f[n]-从n到最后的最大长度;c[n]-存放下一个的下标* 公式:f[n] = max{f[x]} + 1;{x>n && a[n]<=a[x]}* 边界:f[a.length-1] = 1;* */public void negative(int[] a) {int length = a.length;int[] f = new int[length];int[] c = new int[length];// borderf[length-1] = 1;// formulaint i,j;for (i=length-2; i>=0; i--) {// 保存长度int l = 0;// 保存索引int k = 0;for (j=i+1; j<=length-1; j++) {if (l<f[j] && a[i]<=a[j]) {l = f[j];k = j;}}f[i] = l + 1;c[i] = k;}// resultint temp = 0;int index = 0;for (i=0; i<length; i++) {if (temp < f[i]) {temp = f[i];index = i;}}System.out.println("the long of sub sequence : " + temp);System.out.print("the sub sequence is : ");while (index != 0) {System.out.print(a[index] + " ");index = c[index];}}/*** 最长不下降子序列* 正序* 含义:f[n],从起点到当前的最大长度* 公式:f[n] = max{f[x]} + 1;{0<=x<n && a[x]<=a[n]}* 边界:f[0] = 1;* */public void positive(int[] a) {int length = a.length;int[] f = new int[length];int[] c = new int[length];// borderf[0] = 1;// formulaint i,j,l,k;for (i=1; i<length; i++) {l = 0;k = 0;for (j=0; j<i; j++) {if (l<f[j] && a[j]<=a[i]) {l = f[j];k = j;}}f[i] = l + 1;c[i] = k;}// resultint temp = 0;k = 0;for (i=0; i<length; i++) {if (temp < f[i]) {temp = f[i];k = i;}}System.out.println("the long of sub sequence : " + temp);System.out.print("the sub sequence is : ");while (k != 0) {System.out.print(a[k] + " ");k = c[k];}}public static void main(String[] args) {LongSubSequence l = new LongSubSequence();int[] a = new int[]{13,7,9,16,38,24,37,18,44,19,21,22,63,15};l.negative(a);System.out.println("");l.positive(a);}
}

3.走楼梯

【问题】
有 n 级台阶,一个人每次上一级或者两级,问有多少种走完 n 级台阶的方法

【解析】
本质上是斐波那契数列问题
假设只有一个台阶,那么只有一种跳法,那就是一次跳一级,f (1)=1;如果有两个台阶,那么有两种跳法,第一种跳法是一次跳一级,第二种跳法是一次跳两级,f (2)=2。如果有大于 2 级的 n 级台阶,那么假如第一次跳一级台阶,剩下还有 n-1 级台阶,有 f (n-1) 种跳法,假如第一次条 2 级台阶,剩下 n-2 级台阶,有 f (n-2) 种跳法。这就表示 f (n)=f (n-1)+f (n-2)

【代码】

/*** 有 n 级台阶,一个人每次上一级或者两级,问有多少种走完 n 级台阶的方法* 含义:f[n]-走法个数* 公式:f[n] = f[n-1] + f[n-2]* 公式代表第一步走一阶,则有f[n-1],第一步走二阶,则有f[n-2]* */public int positive(int n) {if (n == 1) {return 1;} else if (n == 2) {return 2;} else {int[] f = new int[n+1];f[1] = 1;f[2] = 2;for (int i = 3; i<=n; i++) {f[i] = f[i-1] + f[i-2];}return f[n];}}

4.公共子序列

【问题描述】

一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X=<x1,x2,…,xm>,则另一序列Z=<z1,z2,…,zk>是X的子序列是指存在一个严格递增的下标序列<i1,i2,…,ik>,使得对于所有j=1,2,…,k有:

Xij=Zj

例如,序列Z=<B,C,D,B>是序列X=<A,B,C,B,D,A,B>的子序列,相应的递增下标序列为<2,3,5,7>。给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X=<A,B,C,B,D,A,B>和Y=<B,D,C,A,B,A>,则序列<B,C,A>是X和Y的一个公共子序列,序列 <B,C,B,A>也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列.因为X和Y没有长度大于4的公共子序列。
给定两个序列X=<x1,x2,…,xm>和Y=<y1,y2….yn>.要求找出X和Y的一个最长公共子序列。

【样例输入】
ABCBDAB
BDCABA

【样例输出】
4

【代码】

/*** @author 谢世杰*/
public class LongCommonSequence {/*** 顺序* 两个序列的最长公共子序列** 含义:f[x][y],A序列0...x 和 B序列0...y 的公共子序列最大长度** 分四种情况考虑:* 1.A[x]在公共子序列,B[y]不在,则f[x][y] = f[x][y-1]* 2.A[x]不在公共子序列,B[y]在,则f[x][y] = f[x-1][y]* 3.A[x],B[y]均在,则f[x][y] = f[x-1][y-1] + 1* 4.A[x],B[y]均不在,则f[x][y] = f[x-1][y-1]* 则 f[x][y] 取上述最大值即可,f[x-1][y-1]和f[x-1][y-1]+1 可以合并为后者** 公式:f[x][y] = max{f[x][y-1],f[x-1][y],f[x-1][y-1]+1}* 边界:f[0...x][0] = 0, f[0][0...y] = 0* */public void method(char[] a, char[] b) {int na = a.length;int nb = b.length;int[][] f = new int[na+1][nb+1];// 公式int i,j;for (i=1; i<=na; i++) {for (j=1; j<=nb; j++) {// 考虑a,b中有一个是在目标子串中f[i][j] = f[i-1][j] > f[i][j-1] ? f[i-1][j] : f[i][j-1];// 当a,b都在目标子串中if (a[i-1] == b[j-1]) {f[i][j] = (f[i-1][j-1] + 1) > f[i][j] ? (f[i-1][j-1] + 1) : f[i][j];}}}System.out.println("long = " + f[na][nb]);}public static void main(String[] args) {LongCommonSequence l = new LongCommonSequence();String a = "ABCBDAB";char[] aa = a.toCharArray();String b = "BDCABA";char[] bb = b.toCharArray();l.method(aa,bb);}
}

http://chatgpt.dhexx.cn/article/SjdixDpL.shtml

相关文章

十一、动态规划题目相关

学习来源&#xff1a; 代码随香录&#xff1a;https://www.programmercarl.com/ labuladong算法&#xff1a;https://labuladong.github.io/algo/ 动态规划 动态规划五部曲 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 确定递推公式 dp数组如何初始化 确定遍历…

动态规划题目汇总

文章目录 序言题目一&#xff1a;古生物血缘远近判定题目二&#xff1a;迷宫I题目三&#xff1a;迷宫II题目四&#xff1a;出界的路径数题目五&#xff1a;最长公共字串题目六&#xff1a;最长递增子序列题目七&#xff1a;递增的三元子序列题目八&#xff1a;最长回文字串题目…

动态规划经典例题:不同路径

力扣上比较简答的一道动态规划题目。 方程&#xff1a; class Solution { public:int uniquePaths(int m, int n) {const int M m;const int N n;int dp[M][N];memset(dp, 0, sizeof(dp));for (int i 0; i < m; i) dp[i][0] 1;for (int i 0; i < n; i) dp[0][i] 1;…

动态规划算法与典型例题

目录 前言 一、动态规划要素&#xff08;条件&#xff09; 二、动态规划算法设计步骤 三、复杂度分析 四、典型例题1——游艇租聘 五、典型例题2——0-1背包问题 六、典型例题3——跳台阶问题 七、典型例题4——强盗抢劫问题 总结 前言 动态规划也是一种分治思想&…

动态规划问题经典例题

目录 前言一、字符串分割二、三角矩阵的最小路径和三、路径总数四、最小路径和五、背包问题六、 回文串分割七、编辑距离八、不同的子序列 前言 DP&#xff08;Dynamic Programming&#xff09;定义&#xff1a; 动态规划是分治思想的延伸&#xff0c;通俗一点来说就是大事化小…

动态规划经典题目总结

微信公众号 在算法中&#xff0c;动态规划题目算是比较经典的一类题目。在找工作中&#xff0c;不管是笔试&#xff0c;还是面试&#xff0c;我们经常会遇到用动态规划来解决问题的情况&#xff0c;有时候面试官还需要我们现场手写出动态规划解法的代码。因此&#xff0c;在求职…

【动态规划】经典例题

一.动态规划三要素 1.最优子结构 2.状态转移方程 &#xff08;核心&#xff09;&#xff08;一般用打表找出规律&#xff09; 3.边界值 二.背包问题 &#xff08;一.题目&#xff09; 1.1题目描述 现在有一个背包但容量有限&#xff0c;最多只能装m千克宝石!有n个宝石&…

【动态规划专栏】--基础-- 动态规划经典题型

目录 动态规划 动态规划思维&#xff08;基础&#xff09; 状态表示&#xff08;最重要&#xff09; 状态转移方程&#xff08;最难&#xff09; 初始化&#xff08;细节&#xff09; 填表顺序&#xff08;细节&#xff09; 返回值&#xff08;结果&#xff09; 1、第 …

动态规划入门详解 内含12道经典动态规划编程题

动态规划入门详解 一 什么是动态规划&#xff1f;&#xff1f; 算法导论中介绍&#xff0c;动态规划和分治方法类似&#xff0c;都是听过子问题的解来解决原问题。下面说一下这2者之间的分别&#xff0c;分治方法将原问题划分为互不相交的子问题&#xff0c;而后将子问题组合…

【刷题日记】动态规划经典题目

&#x1f600;大家好&#xff0c;我是白晨&#xff0c;一个不是很能熬夜&#x1f62b;&#xff0c;但是也想日更的人✈。如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下&#x1f440;白晨吧&#xff01;你的支持就是我最大的动力&#xff01;&#x1f4…

Linux命令-sftp文件传输

搭建SFTP服务详见博文&#xff1a;https://blog.csdn.net/cen50958/article/details/90722874 连接SFTP 可使用&#xff1a;sftp --help 查看SFTP的连接参数 [rootstudy ~]# sftp --help usage: sftp [-1Cv] [-B buffer_size] [-b batchfile] [-F ssh_config] [-o ssh_option…

Linux命令(三):SFTP

目录 1、登录 2、文件上传 3、文件下载 4、删除文件/文件夹 5、实战 1、登录 sftp userip 你要用sftp, 当然得登录到sftp服务器&#xff0c; 在linux的shell中执行上面的命令后&#xff0c; linux shell会提示用户输入密码&#xff0c; 我们就输入password吧。 这样就成功…

Linux常用命令——sftp命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) sftp 交互式的文件传输程序 补充说明 sftp命令是一款交互式的文件传输程序&#xff0c;命令的运行和使用方式与ftp命令相似&#xff0c;但是&#xff0c;sftp命令对传输的所有信息使用ssh加密&#xff0c;它还…

SFTP命令常用操作

SFTP相关(等价于rz/sz&#xff0c;此方式适用于没有工具的情况下&#xff0c;前提是保证sftp默认端口22开放) lcd 本地文件路径 进入到本地的某个目录下 cd 远程文件路径 进入到远程的某个目录下 lpwd 显示本地的当前目录的路径 pwd 显示远程的当前目录的路径 这里只介绍常…

SFTP基本功之get、put命令操作

简述 在安装好linux系统之后&#xff0c;开始不断安装部署各种工具&#xff0c;其中很多工具版本太老使得无法使用wget下载&#xff0c;而只能用put命令从本地硬盘中上传之linux系统内安装&#xff0c;而当我编写系统克隆mongodb数据库时&#xff0c;又了解到了get命令&#x…

SFTP命令的使用,sftp传文件

背景&#xff1a;从Windows系统向类unix系统传送文件&#xff0c;使用Windows系统自带的SFTP命令进行文件传送(不用下载F开头&#xff0c;X开头的ftp工具) 背景分割线 上干货&#xff1a;1.WinX&#xff0c;按A&#xff0c;输入SFTP root192.168.162.236 回车&#xff1b; &…

SFTP登录及命令行用法

sftp命令行登录过程 ① sftp xxx.xxx.xxx.xxx 登录&#xff08;默认root用户&#xff09;&#xff0c;若指定用户 sftp bluexxx.xxx.xxx.xxx 进行登录&#xff08;blue为用户名&#xff09; ② 登录成功后&#xff0c;会提示输入 密码 ③ 然后&#xff0c;可进入目录&#xf…

SFTP命令用法(上传和下载 )

一、SFTP SFTP是Secure File Transfer Protocol的缩写&#xff0c;安全文件传送协议。可以为传输文件提供一种安全的网络的加密方法。SFTP与FTP有着几乎一样的语法和功能。SFTP为SSH的其中一部分&#xff0c;是一种传输档案至Blogger伺服器的安全方式。其实在SSH软件包中&…

Linux基础命令 sftp命令的使用

SFTP&#xff08;Secure File Transfer Protocol&#xff0c;安全文件传输协议&#xff09;是一种基于可靠数据流&#xff08;data stream&#xff09;&#xff0c;提供文件存取和管理的网络传输协议&#xff0c;与 FTP 协议相比&#xff0c;SFTP 在客户端与服务器间提供了一种…

sftp常用命令介绍

sftp常用命令&#xff1a; 1. sftp 登录sftp服务器 sftp userip ​​​​​​ 如需要看全部命令&#xff1a;则使用help即可 2. pwd和lpwd 、 ls和lls 、cd和lcd 等 sftp登录之后默认操作是远程服务器&#xff0c;当需要操作本地时&#xff0c;就需要在前边加“l”&#…