动态规划算法

(6.3)动态规划之动态规划例子-矩阵相乘

拥有回忆 提交于 2020-02-05 23:16:45
文章目录 1.问题提出 2.关键计算问题 3.完全加括号的矩阵连乘积 4.矩阵连乘问题 1.问题提出 软件行业中客户总是在变更需求 银行对我们公司开发的乘法模块还不满意。他们的真实想法并不是实现两个矩阵的乘法,而是是能一次够实现多个矩阵按照算法运算法则的乘法,因此要求我们进一步改进我们的系统,实现多个矩阵的连乘功能,并且需要看到我们设计的程序能够满足他们的运行效率要求时才付二期款。 2.关键计算问题 给定n个矩阵{ A 1 A_1 A 1 ​ , A 2 A_2 A 2 ​ ,。。。 A n A_n A n ​ }, 其中 A i A_i A i ​ 与 A i + 1 Ai+1 A i + 1 是可乘的,i=1,2,…n-1。 考察这n个矩阵的连乘积 A 1 A_1 A 1 ​ A 2 A_2 A 2 ​ … A n A_n A n ​ 由于矩阵乘法满足结合律,所以计算矩阵的连乘可以有许多不同的计算次序。这种计算次序可以用加括号的方式来确定 若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积 3.完全加括号的矩阵连乘积 设有四个矩阵 A,B,C,D, 它们的维数分别是: A=50 10 ,B =10 40 ,C = 40 30 D = 30 5 总共有五中完全加括号的方式,及相应的乘法次数如下 (A(

【算法积累】动态规划与斐波那契数列

[亡魂溺海] 提交于 2020-02-04 11:28:27
题目   注:本题来自LeetCode题库70.爬楼梯。 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数。   示例1: 输入: 2 输出: 2 解释: 有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶   示例2: 输入: 3 输出: 3 解释: 有三种方法可以爬到楼顶。 1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶 解法1:动态规划法   不难发现,这个问题可以被分解为一些包含最优子结构的子问题,即它的最优解可以从其子问题的最优解来有效地构建,我们可以使用动态规划来解决这一问题。   假设我们要爬到第n个台阶,则有两种情况:一是爬到第(n-1)个台阶,然后再往上爬1个台阶即可;二是爬到第(n-2)个台阶,然后再往上爬2个台阶即可。也就是说,爬到第n个台阶的方法数,就是爬到第(n-1)个台阶的方法数与爬到第(n-2)个台阶的方法数之和。   特别地,当n=1时,方法数为1;当n=2时,方法数为2(即1+1或直接爬2个台阶)。   代码实现如下: // 语言:C // 执行用时:0ms(又是0ms,具体情况未知) // 内存消耗:6.8MB int climbStairs(int n){ if (n == 1)

最长上升子序列(动态规划)

一个人想着一个人 提交于 2020-02-04 04:48:59
给定一个无序的整数数组,找到其中最长上升子序列的长度。 示例: 输入: [10,9,2,5,3,7,101,18] 输出: 4 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。 说明: 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。 你算法的时间复杂度应该为 O(n2) 。 进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗? 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-increasing-subsequence 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 基于以上思路 class Solution { public : int lengthOfLIS ( vector < int > & nums ) { int len = nums . size ( ) ; if ( len == 0 ) { return 0 ; } vector < int > dp ( len , 0 ) ; int res = 1 ; for ( int i = 0 ; i < len ; i ++ ) { dp [ i ] = 1 ; for ( int j = 0 ; j < i ; j ++ ) { if ( nums [ j ] < nums [

Leetcode 题解 - 动态规划

ぃ、小莉子 提交于 2020-01-28 11:13:07
递归和动态规划都是将原问题拆成多个子问题然后求解,他们之间最本质的区别是,动态规划保存了子问题的解,避免重复计算。 斐波那契数列 Leetcode-70. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数。 示例 1: 输入: 2 输出: 2 解释: 有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶 示例 2: 输入: 3 输出: 3 解释: 有三种方法可以爬到楼顶。 1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶 解法: Java 定义一个数组 dp 存储上楼梯的方法数(为了方便讨论,数组下标从 1 开始),dp[i] 表示走到第 i 个楼梯的方法数目。 第 i 个楼梯可以从第 i-1 和 i-2 个楼梯再走一步到达,走到第 i 个楼梯的方法数为走到第 i-1 和第 i-2 个楼梯的方法数之和。 考虑到 dp[i] 只与 dp[i - 1] 和 dp[i - 2] 有关,因此可以只用两个变量来存储 dp[i - 1] 和 dp[i - 2],使得原来的 O(N) 空间复杂度优化为 O(1) 复杂度。 class Solution { public int climbStairs ( int n ) { if ( n

动态规划

ε祈祈猫儿з 提交于 2020-01-27 06:40:48
动态规划 0-1背包问题 --动态规划,放入n个物体按阶段处理,第n次的结果可以基于第n-1的结果来推导. 最大重量9,物体重量分别为 3,2,4,5 int[n][w]或int[w+1]解决 0-1背包升级版: 一组不同重量、不同价值、不可分割的物品,我们选择将某些物品装入背包,在满足背包最大重量限制的前提下,背包中可装入物品的总价值最大是多少呢? 先计算单价,先放入单价高的商品 有几个节点的 i 和 cw 是完全相同的,比如 f(2,2,4) 和f(2,2,3)。在背包中物品总重量一样的情况下,f(2,2,4) 这种状态对应的物品总价值更大,我们可以舍弃 f(2,2,3) 这种状态,只需要沿着 f(2,2,4) 这条决策路线继续往下决策就可以。也就是说,对于 (i, cw) 相同的不同状态,那我们只需要保留 cv 值最大的那个,继续递归处理,其他状态不予考虑 动态规划理论 一个模型三个特征 一个模型:分阶段最优解模型 三个特征: 1)最优子结构,问题的最优解包含子问题的最优解;也可以通过子问题的最优解推导出问题的最优解 2)无后效性:在推导后面阶段的结果的时候,不关心当前结果怎么获取到的;某阶段的值确定后,就不受之后阶段的决策影响 3)重复子问题:决策序列达到相同阶段时,会产生重复的状态 解决动态规划:面对动态规划问题的时候能够有章可循,不会束手无策 注意

Java数据结构与算法精讲

被刻印的时光 ゝ 提交于 2020-01-23 03:19:40
课程简介 本系列视频教程为数据结构与算法基础,使用java语言描述,适合没有学过C/C++有一定Java基础的同学。没有Java基础的同学可以先行学习Java基础。 课程目录 ├─线性表 ├─栈和队列 ├─HashMap和LinkedHashMap ├─树 ├─二叉树 ├─图 ├─图的遍历与最小生成树 ├─图的最短路径与拓扑排序 ├─算法简介 ├─算法排序 ├─排序与归并 ├─递归与穷举 ├─贪心和分治 ├─动态规划和回溯 来源: CSDN 作者: di_pingxian 链接: https://blog.csdn.net/di_pingxian/article/details/103897423

动态规划

时间秒杀一切 提交于 2020-01-21 00:32:06
动态规划 参考视频av16544031、av18512769 一、重叠子问题 问题 1 回顾斐波那契数列,实质是一个递归关系 也是一个overlap sub-problem 重叠子问题 如果我们要计算fib(7),就会去计算fib(6)和fib(5),之后继续往下,中间fib(6)分解成fib(5)和fib(4),在这部分,我们的fib进行了很多次分解,fib(5)被计算了2次。 算法复杂度会变成O(2^n) 解决方案 将重叠子问题进行保存起来,然后之后再进行取用 二、最优解 问题2 我们有8个task,然后我们中间有重合的时间段,每个task会有一定的收益,怎样才能让收益最高?这是一个典型的dp问题。 解决方案 OPT(optimizations) 最优解 要获得opt,首先得需要思考进行选和不选问题。 If OPT(8) 选择:4+OPT(5) 不选择:OPT(7) 以此类推,我们就可以知道一张prev表 i prev(i) 1 0 2 0 3 0 4 1 5 0 6 2 7 3 8 5 问题3 我们有如下数字, 选出一堆数字,使得不相邻,且加起来结果最大。 解决方案 javascript代码: var arr = [1,2,4,1,7,8,3] var max = (a,b) => a > b ? a:b var rec_opt = (arr,i)=>{ if(i===0)

c++动态规划dp算法题

坚强是说给别人听的谎言 提交于 2020-01-20 07:56:35
问题1:找硬币,换钱的方法 输入: penny数组代表所有货币的面值,正数不重复 aim小于等于1000,代表要找的钱 输出: 换钱的方法总数 解法1:经典dp,空间复杂度O(n*aim) class Exchange { public: int countWays(vector<int> penny, int n, int aim) { if (penny.empty()||n == 0) return 0; vector<vector<int> > dp(n,vector<int>(aim+1)); //二维数组dp for (int i = 0;i < n;i++) { dp[i][0] = 1; } for (int j = 1;j < aim+1;j++) { dp[0][j] = j%penny[0] == 0?1:0; //只需要算dp[0][j] } for (int i = 1;i < n;i++) { for (int j = 1;j < aim+1;j++) { dp[i][j] = (j-penny[i]) >= 0?(dp[i-1][j] + dp[i][j-penny[i]]):dp[i-1][j]; //这是关键,不用管penny【i】到底使用了几次,直接减去1次使用就好 } } return dp[n-1][aim]; } };   解法2

动态规划

早过忘川 提交于 2020-01-20 01:39:57
动态规划 Dynamic Programming 一种设计的技巧,是解决一类问题的方法 dp遵循固定的思考流程:暴力递归 —— 递归+记忆化 —— 非递归的动态规划(状态定义+转移方程) 斐波那契数列 暴力递归,看上去很简洁 def fib(n): return n if n <= 1 else fib(n-1) + fib(n-2) 画出递归树分析一下,可以很容易发现有很多重复计算。 重叠子问题 。 递归算法的时间复杂度怎么计算? 子问题个数乘以解决一个子问题需要的时间。显然,斐波那契数列的递归解法时间复杂度为O(2 n * 1),暴力递归解法基本都会超时。 如何解决? 递归 + 记忆化 仍然使用递归,不同点在于,如果重叠子问题已经计算过,就不用再算了,相当于对冗余的递归树进行了剪枝。 由于不存在重叠子问题,时间复杂度为O(n * 1),降到线性。 1 class Solution: 2 def Fibonacci(self, n): 3 # write code here 4 if n <= 1: 5 return n 6 memo = [-1] * (n+1) 7 memo[0], memo[1]= 0, 1 8 9 def helper(n, memo): 10 if memo[n] >= 0: 11 return memo[n] 12 memo[n] = helper(n

算法设计与分析

☆樱花仙子☆ 提交于 2020-01-15 01:35:56
一、算法思想 (一)分治法(divide and conquer method) 是将待求解的原问题划分成k个较小规模的子问题,对这k个子问题分别求解。如果子问题的规模仍然不够小,则再将每个子问题划分为k个规模更小的子问题,如此分解下去,直到问题规模足够小,很容易求出其解为止(子问题求解思路一致),再将子问题的解合并为一个更大规模的问题的解,自底向上逐步求出原问题的解。 (二)动态规划法(dynamic programing method) 是将待求解问题分解成若干个相互重叠的子问题,每个子问题对应决策过程的一个阶段,一般来说,子问题的重叠关系表现在对给定问题求解的递推关系(也就是动态规划函数)中,将子问题的解求解一次并填入表中,当需要再次求解此子问题时,可以通过查表获得该子问题的解而不用再次求解,从而避免了大量重复计算。 (三)贪心法(greedy method) 贪心法在解决问题的策略上目光短浅,只根据当前已有的信息就做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。换言之,贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优。这种局部最优选择并不总能获得整体最优解(Optimal Solution),但通常能获得近似最优解(Near-Optimal Solution)。 (四)回溯法(back track method)