解决动态规划问题

文章目录

      • 动态规划的定义
      • 动态规划的核心思想
      • 青蛙跳阶问题
        • 解法一:暴力递归
        • 解法二:带备忘录的递归解法(自顶向下)
        • 解法三:动态规划(自底向上)
      • 动态规划的解题套路
        • 什么样的问题考虑使用动态规划?
        • 动态规划的解题思路
      • 第14届JavaB组蓝桥杯“蜗牛”问题

动态规划的定义

动态规划(Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题最优子结构性质的问题。

”dynamic programming is a method for solving a complex problem by breaking it down into a collection of simpler subproblems.“

动态规划就是给定的一个问题拆成一个个子问题,直到子问题可以直接解决。把子问题答案保存起来,以减少重复计算。再根据子问题答案反推,得出原问题解的一种方法。

动态规划的核心思想

拆分子问题,记住过往,减少重复运算。

体现该思想的例子

  • A : “1+1+1+1+1+1+1+1 =?”
  • A : “上面等式的值是多少”
  • B : 计算 “8”
  • A : 在上面等式的左边写上 “1+” 呢?
  • A : “此时等式的值为多少”
  • B : 很快得出答案 “9”
  • A : “你怎么这么快就知道答案了”
  • A : “只要在8的基础上加1就行了”
  • A : “所以你不用重新计算,因为你记住了第一个等式的值为8!动态规划算法也可以说是 ‘记住求过的解来节省时间’”

青蛙跳阶问题

问题:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法。

问题分析:

到达第10级,可以从第9级跳1级台阶,也可以从第8级跳2级台阶。

到达第9级可以从第8级跳1级台阶,也可以从第7级跳2级台阶。

到达第8级可以从第7级跳1级台阶,也可以从第6级跳2级台阶。

定义f(n)为跳到第n级台阶

f(10) = f(9)+f(8)
f (9)  = f(8) + f(7)
f (8)  = f(7) + f(6)
...
f(3) = f(2) + f(1)即通用公式为: f(n) = f(n-1) + f(n-2)
  • 当只有2级台阶时,有两种跳法,第一种是直接跳两级,第二种是先跳一级,然后再跳一级。即f(2) = 2;
  • 当只有1级台阶时,只有一种跳法,即f(1)= 1;
解法一:暴力递归
class Solution {public int Ways(int n) {if(n == 1){return 1;}if(n == 2){return 2;}return Ways(n-1) + Ways(n-2);}
}

时间复杂度:

  • 一个子问题时间 = f(n-1)+f(n-2),也就是一个加法的操作,所以复杂度是 O(1);
  • 问题个数 = 递归树节点的总数= 2n-1,所以是复杂度O(2n)。

总结:

  1. 时间复杂度是指数级别,爆炸式增长,容易超时。
  2. 存在大量重复计算。

改进措施: 使用备忘录,将计算过的答案存下来。省去重复计算的耗时。

解法二:带备忘录的递归解法(自顶向下)

一般使用一个数组或者一个map集合充当备忘录。

	static Map<Integer,Integer> map=new HashMap();private static int ways2(int n) {if(n==1) return 1;if(n==2) return 2;if(map.containsKey(n)) {return map.get(n);}else {map.put(n,(ways(n-1)+ways(n-2)));return ways(n-1)+ways(n-2);}}

时间复杂度:

子问题个数=树节点数=n,解决一个子问题还是O(1),所以带备忘录的递归算法的时间复杂度是O(n)。

解法三:动态规划(自底向上)

动态规划和带备忘录的递归解法基本思想是一致的,都是减少重复计算,时间复杂度也都是差不多。

  • 带备忘录的递归,是从f(10)往f(1)方向延伸求解的,所以也称为自顶向下的解法。
  • 动态规划从较小问题的解,由交叠性质,逐步决策出较大问题的解,它是从f(1)往f(10)方向,往上推求解,所以称为自底向上的解法。

动态规划有几个典型特征,最优子结构、状态转移方程、边界、重叠子问题

在青蛙跳阶问题中:

  • f(n-1)和f(n-2) 称为 f(n) 的最优子结构
  • f(n)= f(n-1)+f(n-2) 称为状态转移方程
  • f(1) = 1, f(2) = 2 是边界
  • 比如f(10)= f(9)+f(8),f(9) = f(8) + f(7) ,f(8)是重叠子问题。

我们来看下自底向上的解法,从f(1)往f(10)方向,一个for循环就可以解决

	private static int ways(int n) {if(n==1) return 1;if(n==2) return 2;int a=1,b=2,temp=0;for(int i=3;i<=n;i++) {temp=a+b;a=b;b=temp;}return temp;}

动态规划的解题套路

什么样的问题考虑使用动态规划?

如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划。

比如一些求最值的场景,如最长递增子序列、最小编辑距离、背包问题、凑零钱问题等等,都是动态规划的经典应用场景。

动态规划的解题思路

动态规划的核心思想就是拆分子问题,记住过往,减少重复计算。 并且动态规划一般都是自底向上的,动态规划的思路如下:

  • 穷举分析
  • 确定边界
  • 找出规律,确定最优子结构
  • 写出状态转移方程

★ 一道动态规划问题,其实就是一个递推问题。假设当前决策结果是f(n),则最优子结构就是要让 f(n-k) 最优,最优子结构性质就是能让转移到n的状态是最优的,并且与后面的决策没有关系,即让后面的决策安心地使用前面的局部最优解的一种性质。

第14届JavaB组蓝桥杯“蜗牛”问题

问题描述:
这天,一只蜗牛来到了二维坐标系的原点。 在 x 轴上长有 n 根竹竿。它们平行于 y 轴,底部纵坐标为 0,横坐标分别为 x1, x2,…, xn。竹竿的高度均为无限高,宽度可忽略。蜗牛想要从原点走到第 n 个竹竿的底部也就是坐标 (xn, 0)。它只能在 x轴上或者竹竿上爬行,在 x 轴上爬行速度为 1 单位每秒;由于受到引力影响,蜗牛在竹竿上向上和向下爬行的速度分别为 0.7 单位每秒和1.3 单位每秒。 为了快速到达目的地,它施展了魔法,在第 i 和 i + 1 根竹竿之间建立了传送门(0 < i < n),如果蜗牛位于第 i 根竹竿的高度为 ai 的位置 (xi , ai),就可以瞬间到达第 i + 1 根竹竿的高度为 bi+1 的位置 (xi+1,bi+1),请计算蜗牛最少需要多少秒才能到达目的地。 输入格式 输入共 1 + n 行,第一行为一个正整数 n; 第二行为 n 个正整数x1, x2, . . . , xn; 后面 n − 1 行,每行两个正整数 ai , bi+1。

输入格式

3
1 10 11
1 1
2 1

输出格式

4.20

样例说明

(0, 0) → (1, 0) → (1, 1) → (10, 1) → (10, 0) → (11, 0),花费时间为 1+1/0.7+0+1/1.3+1 ≈ 4.20

评测用例规模与约定

对于 20% 的数据,保证 n ≤ 15;
对于 100% 的数据,保证 n ≤ 105,ai , bi ≤ 104,xi ≤ 109

问题分析
在这里插入图片描述
每根竹竿有两个出发点,从最底部出发和从传送门出发。自底而上,每次选取最短的路径。

采用动态规划

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);//输入有几根竹竿int n = sc.nextInt();//将n个竹竿的横坐标存放在一个数组gan中.//为了方便,0舍弃不用int[] gan = new int[n + 1];for (int i = 1; i <= n; i++) {gan[i] = sc.nextInt();}//存放每个下标对应竹竿的传送门位置 aiint[] a = new int[n + 1];//存放每个下标对应的传送到的位置  bi+1int[] b = new int[n + 1];//为了方便,0舍弃不用。最后一根竹竿不需要设置传送门afor (int i = 1; i < n; i++) {a[i] = sc.nextInt();b[i + 1] = sc.nextInt();}//新建一个二维数组用来存放,从每个竹竿有两个出发点出发,同样舍弃[0][0],[0][1]不用double[][] dp = new double[n + 1][2];//第一根竹竿出发点有两个dp[1][0] = gan[1];dp[1][1] = gan[1] + a[1] / 0.7;//每行二维数组的第一个数存放从上一根竹竿的两个出发点出发到达这根竹竿底部的路径长短,// 第二个数存放从上一根竹竿的两个出发点出发到达这根竹竿传送门的路径长短for (int i = 2; i < n + 1; i++) {dp[i][0] = Math.min((dp[i - 1][0] + gan[i] - gan[i - 1]), (dp[i - 1][1] + b[i] / 1.3));//如果此竹竿的传送门比传送过来的位置高,则第二种出发点需要往上爬 对应/0.7if (a[i] > b[i]) {dp[i][1] = Math.min((dp[i - 1][0] + gan[i] - gan[i - 1] + a[i] / 0.7), (dp[i - 1][1] + (a[i] - b[i]) / 0.7));} else {dp[i][1] = Math.min((dp[i - 1][0] + gan[i] - gan[i - 1] + a[i] / 0.7), (dp[i - 1][1] + (b[i] - a[i]) / 1.3));}}System.out.printf("%.2f", dp[n][0]);}
}

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

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

相关文章

OR36 链表的回文结构

描述 对于一个链表&#xff0c;请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法&#xff0c;判断其是否为回文结构。 给定一个链表的头指针A&#xff0c;请返回一个bool值&#xff0c;代表其是否为回文结构。保证链表长度小于等于900。 测试样例&#xff1a; 1->…

【C++成长记】C++入门 | 类和对象(中) |类的6个默认成员函数、构造函数、析构函数

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;C❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、类的6个默认成员函数 二、构造函数 1、概念 2、特性 三、析构函数 1、概念 2、特性 一、…

R语言 多组堆砌图

目录 数据格式 普通绘图 添加比例 R语言 堆砌图_r语言堆砌图-CSDN博客 关键点在于数据转换步骤和数据比例计算步骤&#xff0c;然后个性化调整图。 ①data <- melt(dat, id.vars c("ID"))##根据分组变为长数据 ②#计算百分比## data2 <- ddply(data, …

【数据结构】第三节:单链表

前言 本篇要求掌握的C语言基础知识&#xff1a;指针、结构体 目录 前言 单链表 概念 对比链表和顺序表 创建链表 实现单链表 准备工作 打印链表 创建节点并初始化 尾插 二级指针的调用 尾插代码 头插 尾删 头删 查找&#xff08;返回节点&#xff09; 在指定位…

Vue笔记 2

数据代理 数据代理&#xff1a;通过一个对象代理对另一个对象中属性的操作&#xff08;读/写&#xff09; let obj{x:100} let obj2{y:200} Object.defineProperty(obj2,x,{get(){return obj.x},set(value){obj.x value} })Vue中的数据代理 Vue中的数据代理&#xff1a; 通…

Java集合(一)--Map(2)

ConcurrentHashMap与HashTable 底层实现 在JDK1.7时&#xff0c;底层采用的是分段数组&#xff0b;链表的形式&#xff0c;在JDK1.8之后&#xff0c;采用的是与HashMap相同的形式&#xff0c;数组链表/红黑树。而HashTable采用的是数组链表的形式。 如何实现线程安全 Concu…

OpenCV4.9图像金字塔

目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 pyrUp()和 pyrDown()对给定图像进行下采样或上采样。 理论 注意 下面的解释属于 Bradski 和 Kaehler 的 Learning OpenCV 一书。 通常&#xff0c;我们需要将图像转换为与原始图像不同的大小。为此…

spring boot 集成rocketMq + 基本使用

1. RocketMq基本概念 1. NameServer 每个NameServer结点之间是相互独立&#xff0c;彼此没有任何信息交互 启动NameServer。NameServer启动后监听端口&#xff0c;等待Broker、Producer、Consumer连接&#xff0c; 相当于一个路由控制中心。主要是用来保存topic路由信息&#…

Blender表面细分的操作

在使用Blender的过程中,刚开始创建的模型,都会比较少面,这样操作起来比较流畅,减少电脑的计算量,当设计快要完成时,就会增加表面细分,这样更加圆滑,看起来更加顺眼。 比如创建一个猴头,它会默认显示如下: 从上图可以看到,有一些表面会比较大,棱角很多。 这时候你…

微商商城源码小程序好用么?

商城APP作为电子商务行业的重要组成部分&#xff0c;已经成为了人们购物的主要方式之一。为了在竞争激烈的市场中脱颖而出&#xff0c;开发一款专业且思考深度的商城APP方案显得尤为关键。本文将从专业性和思考深度两个方面&#xff0c;探讨商城APP的开发方案。 一、专业性的重…

CloudCompare——win11配置CloudComPy

CloudComPy配置 1 基本环境介绍2 安装Anaconda2.1 下载anaconda2.2 安装anaconda2.3 配置镜像源2.4 更改虚拟环境的默认创建位置2.5 其他问题2.5.1 激活自己创建的环境提示&#xff1a;系统找不到指定的路径2.5.2 InvalidVersionSpecError: Invalid version spec: 2.72.5.3 卸载…

如何解决网站建设打开速度慢的问题?

如何解决网站建设打开速度慢的问题&#xff1f;在浏览网站的时候&#xff0c;网站打开速度的快慢也是能够直接影响到用户的体验感的。因为网站打开速度太慢&#xff0c;不仅浪费了大家的时间&#xff0c;同时还容易消耗浏览者的很大一部分耐心。 所以说不管是对于企业来说&…

hive了解系列一

“ 随着智能手机的普及&#xff0c;互联网时代红利的爆发&#xff0c;用户数量和产生的数据也越发庞大。为了解决这个问题&#xff0c;提高数据的使用价值。 Hadoop生态系统就被广泛得到应用。 在早期&#xff0c;Hadoop生态系统就是为处理如此大数据集而产生的一个合乎成本效益…

C++ 红黑树模拟实现

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C知识分享⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 前言 前面我们实现了AVL树&#xff0c;发明AVL树…

蓝桥杯备赛刷题——css

新鲜的蔬菜 这题需要使用grid 我不会 去学一下 一.什么是grid Grid 布局与 Flex 布局有一定的相似性&#xff0c;都可以指定容器内部多个项目的位置。但是&#xff0c;它们也存在重大区别。 Flex 布局是轴线布局&#xff0c;只能指定"项目"针对轴线的位置&#…

使用冒泡排序模拟实现qsort函数

目录 冒泡排序qsort函数的使用1.使用qsort函数排序整型数据2.使用qsort函数排序结构数据 冒泡排序模拟实现qsort函数今日题目1. 字符串旋转结果2.杨氏矩阵3.猜凶手4.杨辉三角 总结 冒泡排序 冒泡排序的核心思想是:两两相邻的元素进行比较 代码如下: //⽅法1 void bubble_so…

第四百五十四回

文章目录 1. 问题描述2. 优化方法2.1 缩小范围2.2 替代方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取AppBar的高度"相关的内容&#xff0c;本章回中将介绍关于MediaQuery的优化.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 问题描述 我们在…

头歌-机器学习 第13次实验 特征工程——共享单车之租赁需求预估

第1关&#xff1a;数据探索与可视化 任务描述 本关任务&#xff1a;编写python代码&#xff0c;完成一天中不同时间段的平均租赁数量的可视化功能。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 读取数据数据探索与可视化 读取数据 数据保存在./step1/…

Linux C应用编程:MQTT物联网

1 MQTT通信协议 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传 输&#xff09;是一种基于客户端-服务端架构的消息传输协议&#xff0c;如今&#xff0c;MQTT 成为了最受欢迎的物联网协议&#xff0c;已广泛应用于车联网、智能家居、即时聊…

不想升级到win11要怎么取消,怎么拒绝升级win11

微软公布了一个会导致win11数据损坏的罪魁祸首,受到影响的win11系统,是搭载了支持最新VAES指令集的处理器。这次的bug是坑了intel用户呀,Intel从10代酷睿(Ice Lake )和第三代至强可扩展处理器(IceLake-SP)开始才添加了对VAES的支持,AMD这边则是Zen 3锐龙5000,它也是AVX-51…