动态规划算法典型例题

news2024/7/6 17:46:09

这里写目录标题

  • 1、动态规划算法
  • 2、动态规划&分治
  • 3、动态规划算法典型例题
    • 3.1选数问题
      • 3.1.1递归解法
      • 3.1.2动态规划解法
    • 3.2最长公共子序列
    • 3.3钢条切割问题
      • 3.3.1递归解法
      • 3.3.2动态规划解法
    • 3.4斐波那契数列
      • 3.4.1递归解法
      • 3.4.2递归解法
    • 3.5背包问题(0-1背包)

1、动态规划算法

动态规划算法(Dynamic Programming),也叫dp算法,该算法的核心思想是:将大问题划分为小问题进行解决,从而一步步获取最优解;

2、动态规划&分治

动态规划和分治法相似,都是通过组合子问题的解来求解原问题。分治法将问题划分成互不相交的子问题,递归求解子问题,再将他们的解组合起来,求出原问题的解。与之相反,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题。在这种情况下,分治算法会做出许多不必要的工作,它会反复的求解那些公共子问题。而动态规划算法对每个子子问题只求解一次,将结果保存到表格中,从而无需每次求解一个子子问题都要重新计算。
https://blog.csdn.net/u013309870/article/details/75193592
https://blog.csdn.net/a962035/article/details/79943708

3、动态规划算法典型例题

3.1选数问题

题目要求:
假设给定一串数字{1, 2, 4, 1, 7, 8, 3},我们要从中选择若干个数,使最后的和达到最大。选择的规则是,不能选相邻的数字。比如:如果我们选了第一个数字1,那么我们就不能选2,如果我们选择了数字4,那么我们就不能选择与它相邻的2和1。

动态规划的思想:
将整个问题划分成一个个子问题,也就是说要求整个数列的最大和,可以先求出前面若干个数的和,一直划分到求出只有一个数的最大和(即本身),而每个子问题的解对于后面的结果都是有用的,这就是用到了动态规划的思想

思路:
对于每个数,都有选和不选两种状态,如果选了这个数,那么就不能选他相邻的那个数,那么最大和就等于本身加上他相邻的那位数之前那些数的最大和,如果不选这个数,那么便可以选它相邻的那个数,那么最大和就等于这个数之前的那些数的最大和。最终的结果就是取这两种选择的最大值

这里就可以使用递归,即Math.max(dp(arr, x-2)+arr[x], dp(arr, x-1));

递归的出口:

  • 如果只有一个数,那么最大和就是本身
  • 如果只有两个数,那么最大和就是这两个数中的最大值

3.1.1递归解法

/**
* 动态规划之选数问题:递归解法
* @param arr:将给定的一串数字放在数组中
* @param x:数组下标,也就是求出数组第一个元素到这个下标之间的最大和
* @return
*/
public static int dp(int[] arr,int x){
    if(x==0){
        return arr[0];
    }
    if(x==1){
        return Math.max(arr[0], arr[1]);
    }
    return Math.max(dp(arr, x-2)+arr[x], dp(arr, x-1));
}

3.1.2动态规划解法

由于递归会重复计算相同的值,所以我们这里使用非递归解法,也就是创建一个数组来保存计算过的值,由此提高效率。例如temp[0]用来保存数组中只有一个数的最大和,temp[1]用来保存数组中只有两个数的最大和;temp[arr.length()-1]用来保存整个数组的最大和

/**
     * 动态规划之选数问题:非递归解法
     *
     * @return
     */
    public static int dp(int[] arr) {
        int[] temp = new int[arr.length];
        temp[0] = arr[0];
        temp[1] = Math.max(arr[0], arr[1]);
        for (int i = 2; i < arr.length; i++) {
            temp[i] = Math.max(temp[i - 2] + arr[i], temp[i - 1]);
        }
        return temp[arr.length - 1];
    }

3.2最长公共子序列

最长公共子序列问题:longest common subsequence,也叫LCS问题,是动态规划算法的经典例题;解题步骤类似于背包问题,通过创建一个二维数组,并逐步进行填充,通过填表,总结出此问题的公式!

题目描述:
给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的公共子序列是这两个字符串所共同拥有的子序列。

若这两个字符串没有公共子序列,则返回 0。

/**
* 动态规划之最长公共子序列
* @return
*/
public static int longestCommonSubsequence(String text1, String text2) {
    int len1=text1.length();
    int len2=text2.length();
    char[] ch1=text1.toCharArray();
    char[] ch2=text2.toCharArray();

    //动态规划算法创建的二维数组一般都得多增一行一列,这是为了防止数组越界异常
    int[][] p=new int[len1+1][len2+1];

    //填表,第一行和第一列都为0,所以填表从下标为1的行和下标为1的列开始填
    for(int i=1;i<p.length;i++){
        for(int j=1;j<p[0].length;j++){
            if(ch1[i-1]==ch2[j-1]){
                p[i][j]=p[i-1][j-1]+1;
            }else{
                p[i][j]=Math.max(p[i-1][j], p[i][j-1]);
            }
        }
    }	
    return p[len1][len2];
}

3.3钢条切割问题

在这里插入图片描述

3.3.1递归解法

/**
     * @param p 长度-价格
     * @param n 钢条长度
     * @return 最大收益
     */
    public static int cut(int[] p, int n) {

        if (n == 0)
            return 0;
        int q = Integer.MIN_VALUE;
        for (int i = 1; i <= n; i++) {
            q = Math.max(q, p[i - 1] + cut(p, n - i));
            System.out.println(q);
        }
        return q;
    }

3.3.2动态规划解法

  public static int buttom_up_cut(int[] p, int n) {
        int[] r = new int[p.length + 1];
        for (int i = 1; i <= n; i++) {
            int q = -1;
            for (int j = 1; j <= i; j++)
                q = Math.max(q, p[j - 1] + r[i - j]);
            r[i] = q;
        }
        return r[n];
    }

3.4斐波那契数列

3.4.1递归解法

public int fib(int n)
{
	if(n<=0)
		return 0;
	if(n==1)
		return 1;
	return fib( n-1)+fib(n-2);
}
//输入6
//输出:8


3.4.2递归解法

public static int fib(int n)
	{
		if(n<=1)
			return n;
		
		int Memo_i_2=0;
		int Memo_i_1=1;
		int Memo_i=1;
		for(int i=2;i<=n;i++)
		{
			Memo_i=Memo_i_2+Memo_i_1;
			Memo_i_2=Memo_i_1;
			Memo_i_1=Memo_i;
		}		
		return Memo_i;
	}

3.5背包问题(0-1背包)

https://www.bilibili.com/video/BV1Mf4y1y7WD/?spm_id_from=333.337.search-card.all.click&vd_source=52f9eb63aa834f8c039c3dedc7463736
题目描述:
在这里插入图片描述

public static void main(String[] args) {
        int[] w = {2, 2, 6, 5, 4};//物品的重量,分别表示吉他1磅,音响4磅,电脑3磅
        int[] v = {6, 3, 5, 4, 6};//物品的价值,分别表示吉他1500,音响4000,电脑3000

        int m = 10;//背包的容量
        int n = w.length;//物品的个数

        //创建一个二维数组
        int[][] p = new int[n + 1][m + 1];//将物品多增一行和背包的容量多增一列是为了防止后面的公式出现数组越界异常

        //填表,注意是从下标为1的那一行以及下标为1的那一列开始填的
        for (int i = 1; i < p.length; i++) {
            for (int j = 1; j < p[0].length; j++) {
                //因为下标是从1开始,所以w数组的下标要减一
                if (j < w[i - 1]) {
                    //将上一行对应列的单元格的值赋给当前位置
                    p[i][j] = p[i - 1][j];
                } else {
                    //j>=w[i-1]的情况

                    //p[i-1][j]表示上一行对应列的单元格的值,也就是没有新增当前商品之前对应重量的最大价值
                    //v[i-1]表示当前商品的价值,注意下标也是要减一
                    //j-w[i-1]表示当前容量减去当前物品的容量后剩余容量
                    //p[i-1][j-w[i-1]]表示没有加入当前商品前剩余这个容量对应的最大价值
                    p[i][j] = Math.max(p[i - 1][j], v[i - 1] + p[i - 1][j - w[i - 1]]);
                }
            }
        }

        //输出填写的二维数组
        for (int i = 0; i < p.length; i++) {
            for (int j = 0; j < p[0].length; j++) {
                System.out.print(p[i][j] + "\t");
            }
            System.out.println();
        }
        System.out.println("能装入的最大价值为:" + p[p.length - 1][p[0].length - 1]);
    }

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

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

相关文章

SRS服务器搭建以及展现配置说明

对于企业而言&#xff0c;数字化建设是一项全面的、系统的工程&#xff0c;不仅仅只是部署几套软件、实现办公自动化而已&#xff0c;尤其是大型企业&#xff0c;数字化的建设往往涉及到了服务器、硬件、软件、网络等一系列内容。如门禁系统和人力、认证等系统集成&#xff0c;…

计算机视觉与图形学-神经渲染专题-非刚体NeRF II

《TiNeuVox:Fast Dynamic Radiance Fields with Time-Aware Neural Voxel》链接&#xff1a;https://jaminfong.cn/tineuvox/摘要作者通过表示具有时间感知体素特征的场景提出了一个辐射场框架&#xff0c;并将其命名为 TiNeuVox。作者引入了一个微小的坐标变形网络来模拟粗略的…

Flink-使用合流操作进行实时对账需求的实现

学Flink第八章多流转换的时候&#xff0c;进行合流操作.connect()使用到了第九章状态编程的知识&#xff0c;感觉总体不是很清晰&#xff0c;因此学完状态编程后现在进行重温并细化一些细节 业务背景 步骤一&#xff1a; 用户进行支付的时候&#xff0c;后台是需要调用第三方…

leetcode 834. Sum of Distances in Tree(树中的距离和)

无向连接的树&#xff08;不一定是二叉树&#xff09;&#xff0c;求每个节点到其他节点的距离和。 返回一个数组&#xff0c;数组的第i个元素就是第i个节点到其他所有节点的距离之和。 思路&#xff1a; 涉及无向图的构造和遍历&#xff0c;树的前序后序遍历&#xff0c;问题…

论文复现-1:Perturbation CheckLists for Evaluating NLG Evaluation Metrics

以data2text任务为例&#xff0c;探讨generation metric矩阵对于一些句子扰动是否敏感&#xff0c;在多个维度上的敏感性如何&#xff1f; 1数据集 data2text数据集是由3025条samples构成&#xff0c;关键词由“ID”和“reference”构成。 每个子任务由对应的criteria&#…

python基础语法19-calendar模块

一、简介 有了time及datetime模块&#xff0c;再结合日历&#xff08;Calendar&#xff09;模块就可以更好的覆盖到时间处理的各个方面的应用。日历模块主要是用于处理日历及星期相关操作。 calendar模块的内置函数如下: 序号 函数及描述 1 calendar.calendar(yea…

Keras深度学习实战(42)——强化学习基础

Keras深度学习实战&#xff08;42&#xff09;——强化学习基础0. 前言1. 强化学习基础1.1 基本概念1.2 马尔科夫决策过程1.3 目标函数2. 在具有非负奖励的模拟游戏中获取最佳动作2.1 问题设定2.2 模型分析2.3 模型构建与训练3. 在模拟游戏中获取最佳动作3.1 问题定义3.2 模型分…

数据库原理及MySQL应用 | 数据表操作

数据表操作是数据库操作中最基本和最重要的操作。 图5-1是图书销售数据库booksale中存放的图书表books。 ■ 图5-1图书表books 01. 表的结构 表的结构也称为“型”(Type)&#xff0c;用于描述存储于表中的数据的逻辑结构和属性。定义表就是指定义表的结构&#xff0c;使用数据…

Vue CLI系列之生成打包报告

文章の目录一、通过命令行参数的形式生成报告二、通过可视化的UI面板直接查看报告写在最后打包时&#xff0c;为了直观地发现项目中存在的问题&#xff0c;可以在打包时生成报告。生成报告的方式有两种&#xff1a; 一、通过命令行参数的形式生成报告 "scripts": {…

关于对计算机发展史、冯诺依曼体系、CPU基本工作流程以及关于编程语言的简单认识

关于计算机发展史&#xff1a; 关于计算机发展史&#xff0c;大体经历了从一般计算工具到机械计算机到目前的电子计算机的发展历程。 公元前2500年&#xff0c;算盘已经出现&#xff1b; 1694 年&#xff0c;德国博物学家 戈特弗里德莱布尼兹建造了“步进计算器”。 关于步进…

Djiango实现用户管理增删改成功能实战

1.0定义 前后端不分离模式 前后端分离是指前端页面看到的效果都是由后端控制&#xff0c;即后端渲染HTML页面&#xff0c;前端与后端的耦合度比较高 前后端分离模式 后端仅返回前端所需要的数据&#xff0c;不在渲染HTML页面&#xff0c;不在控制前端的效果&#xff0c;至…

八、kubernetes1.25应用升级、回滚

1、概述 用户希望应用程序始终可用&#xff0c;而开发人员则需要每天多次部署它们的新版本。在 Kubernetes 中&#xff0c;这些是通过滚动更新&#xff08;Rolling Updates&#xff09;完成的。 滚动更新 允许通过使用新的实例逐步更新 Pod 实例&#xff0c;零停机进行 Deploym…

Sentinel流控

Sentinel 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 1.sentinel特性 Sentinel 具有以下特征: 丰富的应用场景&#xff1a; Sentinel 承接了…

最优化方法——最小二乘法与梯度下降法

目录 系列文章目录 一、问题 二、实验思路综述 1.实验工具及算法 2.实验数据 3.实验目标 4.实验步骤 三、最小二乘问题引入 1.最小二乘问题样例 2.最小二乘问题解决方案及数学模型化 3.相关线性代数知识导入 3.1 梯度 3.2 矩阵的逆 3.3 QR分解 四、最小二乘法 …

用 ChatGPT 运行 Python

最近&#xff0c;我一直在阅读一些关于ChatGPT的有趣文章。在一篇文章中&#xff0c;有人发明了一种新的语言&#xff0c;并让ChatGPT运行它。在另一篇文章中&#xff0c;有人在ChatGPT中运行一个虚拟机。后者启发我提出了下面这个问题。你能在ChatGPT中运行一个交互式Python会…

【docker常用命令】

一、帮助启动类命令 &#xff08;1&#xff09;启动docker systemctl start docker&#xff08;2&#xff09;停止docker systemctl stop docker&#xff08;3&#xff09;重启docker systemctl restart docker&#xff08;4&#xff09;查看docker状态 systemctl status…

【数据预处理】基于Pandas的数据预处理技术【california_housing加州房价数据集】_后9个任务

文章目录一.需求分析二.需求解决2.1 对第一个特征&#xff08;收入中位数&#xff09;排序后画散点图2.2 对第一个特征&#xff08;收入中位数&#xff09;画分位数图并分析2.3 【选做】对所有特征画分位数图并进行分析2.4 使用线性回归方法拟合第一个特征&#xff08;收入中位…

基于c# asp.net电子病历管理系统的设计与实现

摘 要 网络的广泛应用给生活带来了十分的便利。所以把电子病历管理与现在网络相结合&#xff0c;利用net语言建设电子病历管理系统&#xff0c;实现电子病历管理的信息化。则对于进一步提高医院的发展&#xff0c;丰富电子病历管理经验能起到不少的促进作用。 电子病历管理系统…

AbstractQueueSynchronizer

AbstractQueueSynchronizer AbstractQueueSynchronizer 是基于 FIFO线程等待队列 的一个同步器开发框架。 这篇文章首先介绍同步器概念&#xff0c;然后介绍AQS的结构原理 什么是Synchronizer&#xff08;同步器&#xff09; 并发环境下&#xff0c;Synchronizer用于实现线…

Windows和Mac系统实现本地部署WebPageTest工具

在项目开发或者测试的过程中&#xff0c;由于没有上线&#xff0c;我们在公网上无法访问我们的网站&#xff0c;但同时我们又需要查看浏览器性能&#xff0c;这样我们就需要在本地部署WebPageTest工具以协助进行性能测试 具体实现步骤&#xff1a; Windows系统&#xff1a; …