动态规划算法

leetcode 70 爬楼梯(动态规划)

ε祈祈猫儿з 提交于 2020-01-15 01:00:10
假设你正在爬楼梯。需要 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 阶 暴力搜索,回溯法 //超时 class Solution { public : int climbStairs ( int n ) { if ( n == 1 || n == 2 ) { return n ; } return climbStairs ( n - 1 ) + climbStairs ( n - 2 ) ; } } ; 第i阶的爬法数量 = 第i-1阶的爬法数量 + 第i-2阶的爬法数量 算法思路: 1、设置递推数组dp[0……n],dp[i]代表到达第i阶,有多少种走法,初始化数组元素为0 2、设置到达第1阶台阶,有1种走法,到达第2阶台阶有2种走法 3、利用i循环递推从第3阶至第n阶结果 class Solution { public : int climbStairs ( int n ) { vector < int > dp ( n + 3 , 0 )

POJ3181 Dollar Dayz 动态规划 背包解法 解题报告

陌路散爱 提交于 2020-01-13 13:23:01
题目链接: http://acm.pku.edu.cn/JudgeOnline/problem?id=3181 题目大意: 输入n,和k,问将n用1到k这k个数字进行拆分,有多少种拆分方法。例如: n=5,k=3 则有n=3+2,n=3+1+1,n=2+1+1+1,n=2+2+1,n=1+1+1+1+1这5种拆分方法 解题思路: 这个题目是个比较明显的动态规划,如果想不到是背包问题,也可以写出状态转移方程如下: 用a[i][j]表示考虑到用数j进行拼接时数字i的拼接方法,可以得到状态转移方程如下: a[i][j]=a[i][j-1]+a[i-j][j-1]+a[i-2j][j-1]+a[i-3j][j-1]…+a[0][j-1]意思很明显,就将j-1状态可以到达a[i][j]的状态的数字相加。由于得到的结果可能相当大,已经超过了long long,所以应该用大数。但是若跑完所有数据,用大数会超过一秒,我们通过大数的程序可以达到,最大的数字为33位,那么,我们可以将两个long long的数字进行拼接,组成一个超过33位的数。这样增加了速度,这种比较慢的算法也可以不超时。ac的代码如下: #include <iostream> #include<cstdio> using namespace std; long long a[1200][200]={0},b[1200][120]=

动态规划-Minimum Distance to Type a Word Using Two Fingers

删除回忆录丶 提交于 2020-01-12 19:23:44
2020-01-12 18:28:13 问题描述 : 问题求解 : 本题还是非常困难的,至少我在看到这个题目的时候是没有想到怎么解决的。我当时联想到的题目是那条grid走两遍的题目,那条题目也很麻烦,使用的是dp。 本题最终的解决方式其实是和那条题目是类似的,也是使用dp的方式去做。 最大的类似在于,这两题都可以使用dfs + me来进行解决,dfs和dp任何一个都是解决问题的大杀器,他们的结合就更是非常的厉害。很多的题目直接使用自底向上的dp是不容易写的,但是结合dfs使用me的dp则非常的直观并且效率依然很高。 这两条题目都是采用的这个算法,结构清晰且逻辑严明,本质上都是解空间的遍历,但是利用了dp的思路将其中的一些解保存了下来方便了后续的计算。 int[][][] dp = new int[27][27][301]; public int minimumDistance(String word) { return helper(word, 0, 0, 0); } private int helper(String word, int start, int l, int r) { if (start >= word.length()) return 0; if (dp[l][r][start] != 0) return dp[l][r][start]; int idx =

【数据结构46】动态规划算法--01背包问题

浪子不回头ぞ 提交于 2020-01-11 02:04:51
public class KnapsackProblem { public static void main ( String [ ] args ) { int [ ] w = { 1 , 4 , 3 } ; //物品的重量 int [ ] val = { 1500 , 3000 , 2000 } ; //物品的价值 int m = 4 ; //背包的容量 int n = val . length ; //物品的个数 //创建二维数组,v[i][j]表示前i个物品能够装入容量为j的背包中的最大值 int [ ] [ ] v = new int [ n + 1 ] [ m + 1 ] ; //为了记录放入商品的情况,定义一个二维数组 int [ ] [ ] path = new int [ n + 1 ] [ m + 1 ] ; //初始化第一行第一列 for ( int i = 0 ; i < v . length ; i ++ ) { v [ i ] [ 0 ] = 0 ; //初始化第一列 } for ( int i = 0 ; i < v [ 0 ] . length ; i ++ ) { v [ 0 ] [ i ] = 0 ; //初始化第一行 } //根据前面的公式来动态规划处理 for ( int i = 1 ; i < v . length ; i ++ ) { /

9动态规划

拥有回忆 提交于 2020-01-09 23:01:39
1.背包问题 音响 3000元 4斤 笔记本电脑 2000元 3斤 吉他 1500元 1斤 1.简单算法 最简单的算法:尝试各种可能的商品组合,并找出价值最高的组合。 缺点:速度非常慢。3种商品需要计算8种组合;4件商品是,需要计算16中组合。每增加一种商品,需要计算的集合数将翻倍。这种算法的运行时间为O(2 n ) 组合1 组合2 组合3 组合4 无 吉他 音响 笔记本电脑 0 1500 3000 2000 组合5 组合6 组合7 组合8 吉他和音响 吉他和笔记本电脑 音响和笔记本电脑 吉他、音响和笔记本电脑 装不下 3500 装不下 装不下 近似算法可以得到近似解,但不一定是最优解。 2. 动态规划 使用动态规划可以得到最优解。 背包的承重为1斤 背包的承重为2斤 背包的承重为3斤 背包的承重为4斤 吉他 1 1500 可以放入背包 G 1500 可以放入背包 G 1500 可以放入背包 G 1500 可以放入背包 G 1500 音响 4 3000 G 1500 G 1500 G 1500 S 3000 笔记本电脑 3 2000 G 1500 G 1500 C 2000 3000 vs (2000+1500) -> 3500 计算公式: cell[i][j] = cell[i-1][j] vs {当前商品的价值 + 剩余空间的价值 = 当前商品的价值+cell[i-1][j

算法分类合集

二次信任 提交于 2020-01-06 08:18:08
算法分类合集 ACM 所有 算法 数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维线段树 树状数组 一维树状数组 N维树状数组 字典树 后缀数组,后缀树 块状链表 哈夫曼树 桶,跳跃表 Trie树(静态建树、动态建树) AC自动机 LCA和RMQ问题 KMP算法 图论 基本图算法图 广度优先遍历 深度优先遍历 拓扑排序 割边割点 强连通分量 Tarjan算法 双连通分量 强连通分支及其缩点 图的割边和割点 最小割模型、网络流规约 2-SAT问题 欧拉回路 哈密顿回路 最小生成树 Prim算法 Kruskal算法(稀疏图) Sollin算法 次小生成树 第k小生成树 最优比例生成树 最小树形图 最小度限制生成树 平面点的欧几里德最小生成树 平面点的曼哈顿最小生成树 最小平衡生成树 最短路径 有向无环图的最短路径->拓扑排序 非负权值加权图的最短路径->Dijkstra算法(可使用二叉堆优化) 含负权值加权图的最短路径->Bellmanford算法 含负权值加权图的最短路径->Spfa算法 (稠密带负权图中SPFA的效率并不如Bellman-Ford高) 全源最短路弗洛伊德算法Floyd 全源最短路Johnson算法 次短路径

【经典算法】动态规划

二次信任 提交于 2020-01-04 01:03:47
目录 斐波那契数列的启发 第一个例子 第二个例子 参考资料 斐波那契数列的启发 在讨论动态规划之前,我们先看一个熟悉的例子——斐波那契数列(Fibonacci sequence): 如果我想求 f ( 3 ) f(3) f ( 3 ) ,那我只要知道 f ( 1 ) f(1) f ( 1 ) 和 f ( 2 ) f(2) f ( 2 ) 就可以了,同理,如果想知道 f ( 4 ) f(4) f ( 4 ) ,那我需要知道 f ( 2 ) f(2) f ( 2 ) 和 f ( 3 ) f(3) f ( 3 ) 。以此类推,如果我想知道 f ( n ) f(n) f ( n ) ,那么只要已知 f ( 1 ) . . . f ( n − 1 ) f(1)...f(n-1) f ( 1 ) . . . f ( n − 1 ) 即可。对于像具有像斐波那契数列这样递推关系的问题,都可以用这种方法求解。虽然这样看上去有点笨,却是一个用空间换时间的高效方法,因为这样时间复杂度就能降到 O ( n ) O(n) O ( n ) ,而用递归的方法时间复杂度可能达到 O ( 2 n ) O(2^n) O ( 2 n ) 。下面我们看一个例子: 第一个例子 对于数组 [ a 1 a 2 . . . a n ] [a_1\ a_2 \ ... \ a_n] [ a 1 ​ a 2 ​ . . . a n

动态规划 ——0-1背包问题(1)

回眸只為那壹抹淺笑 提交于 2019-12-31 21:42:55
0-1背包问题 本文内容来来源于《计算机算法设计与分析》(王晓东著),是笔者的学习笔记,内容不当处,欢迎留言探讨 问题描述:给定n中物品和一背包,物品i的重量是 w i w_i w i ​ ,价值为 v i v_i v i ​ ,背包容量为c。应如何选择装入背包中的物品,使得装入背包中物品的总价值最大。 目标函数: m a x ∑ i = 1 n v i x i max\sum_{i=1}^{n}v_ix_i m a x i = 1 ∑ n ​ v i ​ x i ​ 即装入背包中的物品价值达到最大。 约束条件: ∑ i = 1 n v i x i < c \sum_{i=1}^{n}v_ix_i<c ∑ i = 1 n ​ v i ​ x i ​ < c ,即装入背包中的物品总重量小于背包的容量。 好吧,其实我看到这里已经要睡着了,脑子里想到的画面是装到背包里的东西,和重量有个线球关系,你该考虑的不该是体积么,反正我装背包,从来不担心重量。不过不要紧,清醒一下,洗把脸,心里默念,去~~~的 1、最优子结构 动态规划的本质是对问题进行分解,对每个子问题求解,从而得到原问题的解,当然,其灵魂是建立一个表格,或者什么都行,存储一部分子问题的解,避免进行重复计算。 设 ( y 1 , y 2 . . . y n ) (y_1,y_2...y_n) ( y 1 ​ , y 2 ​ . .

0-1背包问题 动态规划算法 C++

余生长醉 提交于 2019-12-25 16:35:11
简单的0-1背包问题,使用动态规划的算法。 # include <iostream> # include "stdio.h" # include "stdlib.h" using namespace std ; int m [ 10 ] [ 10 ] ; int p [ 10 ] ; //价值 int w [ 10 ] ; //重量 void backpack ( int n , int c ) { for ( int i = 0 ; i < 10 ; i ++ ) { m [ 0 ] [ i ] = 0 ; m [ i ] [ 0 ] = 0 ; } for ( int i = 1 ; i <= n ; i ++ ) { for ( int j = 1 ; j <= c ; j ++ ) { if ( j < w [ i ] ) m [ i ] [ j ] = m [ i - 1 ] [ j ] ; if ( j >= w [ i ] ) { if ( m [ i - 1 ] [ j ] >= m [ i - 1 ] [ j - w [ i ] ] + p [ i ] ) m [ i ] [ j ] = m [ i - 1 ] [ j ] ; else { m [ i ] [ j ] = m [ i - 1 ] [ j - w [ i ] ] + p [ i ] ; } } }

JavaScript 算法系列---动态规划

被刻印的时光 ゝ 提交于 2019-12-24 12:27:18
很久之前接触过这样一道题目,总共有十层阶梯,从1层开始往上爬,每次可以上1层或者2层,问到10层总共有多少种方法? 思路:这个问题就是动态规划的一个经典例子,所谓动态规划,就是把复杂的问题进行拆解,拆解成一个个子问题,而这类问题最后非常适合使用递归来解决。诸如这道题目,可以记到某层阶梯的走法为F(n),那么到10层阶梯就是F(10)。 那么F(10)等于什么呢,这里进行假设,如果只差 最后一次 就可以走到10层,那么此时有几种情况呢? 在9层,往上走1步即可。 在8层,往上走2步即可。 那么此时可以得出F(10)=F(9)+F(8); — 最优子结构 其实这里就可以得出F(n)=F(n-1) + F(n-2) — 状态转移方程 而当n=2时,也就是走上2层,马上可以知道只有2种方法(0->2,0->1->2) 也就是F(2)=2,同理F(1)=1. — 边界情况 写成代码也很容易,这里就不写了。 然后这次还遇到了一个类似的题目,源自力扣 链接 其实大致的思路还是一样的,只是增加了对二维数组中,某一个数字的判断逻辑,刚刚开始我是这样做的 /** * @param {number[][]} obstacleGrid * @return {number} */ var uniquePathsWithObstacles = function(obstacleGrid) { //