动态规划(Dynamic Programming)


理解动态规划的好文:https://www.sohu.com/a/153858619_466939


1、基础

**定义:**递归算法经常会有一些重复的计算,导致程序效率低。动态规划就是解决这个问题的方法。

动态规划的组成部分:

  • 最优子结构:分解问题
  • 边界:递归的终止条件
  • 状态转移方程:递归的方程

动态规划的解题步骤:

  • 分解问题,得到状态转移方程
  • 暴力搜索,找到冗余,通常用纯递归
  • 存储已经计算过的结果,通常用数组和字典
  • 编程时通常采用自底向上思想(递推)

2、走台阶问题

**题目:**有一座10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。要求用程序来求出一共有多少种走法。

递归解法:

int solve(int n)
{if(n < 1)return 0;if(n == 1)return 1;if(n == 2)return 2;return solve(n-1)+solve(n-2);
}

备忘录解法:

int solve(int n,HashMap<Interger, Interger>map)
{if(n < 1)return 0;if(n == 1)return 1;if(n == 2)return 2;if(map.contains(n))return map.get(n);else{int value = solve(n-1)+solve(n-2);map.put(n, value);return value;}
}

动态规划解法:

int solve(int n,HashMap<Interger, Interger>map)
{if(n < 1)return 0;if(n == 1)return 1;if(n == 2)return 2;int a = 1;int b = 2:int temp = 0;for(int i=3; i<=n; i++){temp = a + b;a = b;b = temp;}return temp;
}

题目改为一次最多能走k阶台阶

思路:其实是一样的,只要把边界和递归式扩展到 k 即可

// 边界条件, 转化为总共 k 阶台阶,可以任意走,到达k阶有2^(k-1)种走法
num[0] = 1
for(int i=1; i =< k; ++i)num[i] = power(2, i-1);// 递推
for(int j = k+1; j<n+1; ++j)
{z = 1;while(z < k){num[j] += num[j-z];z += 1;}
}

3、打家劫舍问题

**题目:**偷商店,不能连续偷两家,求偷的总额最大

备忘录解法:

vector<int> save;
int solve(vector<int>& nums, int n)
{if(n < 0)return 0;if(save[n] >= 0)return save[n];save[n] = max(solve(nums, n-2)+nums[n], solve(nums, n-1));return save[n];
}
int rob(vector<int>& nums) {int len = nums.size();for(int i=0; i<len; i++)save.push_back(-1);return solve(nums, len-1);
}

动态规划解法:

int rob(vector<int>& nums) {int n = nums.size(); if(n == 0)return 0;if(n == 1)return nums[0];vector<int> save(n, -1);save[0] = nums[0];save[1] = max(nums[0], nums[1]);for(int i=2; i<n; ++i)save[i] = max(nums[i]+save[i-2], save[i-1]);return save[n-1];

4、01背包问题

题目: 给定 n 种物品和一个容量为 C 的背包,物品 i 的重量是 wi,其价值为 vi ,应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大?

// 下标为0的元素,没有用到,置为0
int v[N]={0,8,10,6,3,7,2};
int w[N]={0,4,6,2,2,5,1};
int n=6,c=12;int solve()
{// 需要知道的初始值是 m[i][0],m[0][j] 都等于0,所以数组都初始化为0int m[n+1][c+1] = {0};for(int i=1;i<=n;i++){for(int j=1;j<=c;j++){if(j>=w[i])m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);  elsem[i][j]=m[i-1][j];}}return m[n][c]

可以进一步压缩空间,只用2x(c+1)或1x(c+1)大小的数组:

# 2x(c+1)数组
int m[2][c+1] = {0};
m[i%2][j]=max(m[(i-1)%2][j],m[(i-1)%2][j-w[i]]+v[i]);  # 1x(c+1)大小的数组
int m[c+1] = {0};
m[j]=max(m[j],m[j-w[i]]+v[i]);  

5、硬币找零

题目: 硬币的种类值列表 coin_list,要找零钱 change 元,问最少需要几个硬币?

递归解法:

def find_coins(coin_list, change):min_coins = changeif change in coin_list:return 1else:for i in [c for c in coin_list if c <= change]:num_coins = 1 + find_coins(coin_list, change-i)if num_coins < min_coins:min_coins = num_coinsreturn min_coinsprint(recDC([1,5,10,25], 63)

备忘录解法:

# save_list 缓存已经算过的零钱最少找币数,列表大小=最初需要找零的值+1,初始值都=0
def find_coins(coin_list, change, save_list):min_coins = changeif change in coin_list:return 1elif save_list[change] > 0:return save_list[change]else:for i in [c for c in coin_list if c <= change]:num_coins = 1 + find_coins(coin_list, change-i, save_list)if num_coins < min_coins:min_coins = num_coinssave_list[change] = min_coinsreturn min_coinsprint(recDC([1,5,10,25], 63, [0]*64))

动态规划解法:

# 递推
def find_coins(coins_list, change, min_coins_list):for num in range(change+1):num_coins = numfor j in [c for c in coins_list if c <= num]:if min_coins_list[num-j] + 1 <= num_coins:num_coins = min_coins_list[num-j]+1min_coins_list[num] = num_coinsreturn min_coins_list[change]print(find_coins([1, 5, 10, 25], 63, [0]*64))

GOOD LUCK!


数据结构与算法(C++)– 动态规划(Dynamic Programming)相关推荐

  1. 算法导论-动态规划(dynamic programming)

    动态规划:通过组合子问题的解来解决整个问题. 动态规划的四个步骤: 1)描述最优解的结构: 2)递归定义最优解的值: 3)按自低向上的方式计算最优解的值(首先找到子问题的最优解,解决子问题,最后找到问 ...

  2. 算法初探-动态规划(Dynamic Programming)

    编程之中接触到很多关于算法的知识,想来整理一番,算是对自己记忆的一个提醒 1.Coin11Problem  问题为:使用最少的三种面值为1,3,5的硬币组合出11元. 重要的是状态以及状态转移方程 d ...

  3. 数据结构与算法学习⑥(动态规划 题解 背包和打家劫舍问题)

    数据结构与算法学习⑥(动态规划 动态规划 1.初识动态规划 1.1.从贪心说起 1.1.1.贪心的特点 1.1.2.贪心的局限性 1.1.3.贪心失效后怎么办 1.1.4.从最优化问题到递归 1.2. ...

  4. 动态规划 dynamic programming

    动态规划dynamic programming June,7, 2015 作者:swanGooseMan 出处:http://www.cnblogs.com/swanGooseMan/p/455658 ...

  5. 动态规划(Dynamic Programming)的一些事一些情

    References <算法导论> 最近在回顾算法的知识,特将一些动态规划的重点记录下来,好让以后自己不要忘记. 基本概念 动态规划(Dynamic Programming,简称为DP,下 ...

  6. 运筹学状态转移方程例子_动态规划 Dynamic Programming

    从运筹学和算法的角度综合介绍动态规划 规划论 Mathematical Programming / Mathematical Optimization In mathematics, computer ...

  7. 动态规划(Dynamic Programming)与贪心算法(Greedy Algorithm)

    文章目录 动态规划算法(Dynamic Programming) 动态规划问题的属性 应用实例:最长公共子序列问题(Longest Common Subsequence, LCS) 贪心算法(Gree ...

  8. 动态规划|Dynamic Programming

    由于最近课设要用动态规划,翻阅资料学习一下. 动态规划 解决复杂问题的方法,把它们分解成更简单的子问题. 一旦我们看到一些例子,这个定义就有意义了.实际上,我们今天只看解问题的例子 解决DP问题的步骤 ...

  9. [欠驱动机器人]4,动态规划(Dynamic Programming)

    目录 前言 控制问题变成优化问题 新增成本(Additive cost) 图搜索的最优控制 连续动力学方程 HJB 方程 求出最小控制 数值求解J 方程逼近与数值迭代 线性方程逼近 网格上的值迭代 连 ...

  10. 数据结构和算法——用动态规划求解最短路径问题

    一.动态规划求解问题的思路     在<算法导论>上,动态规划的求解过程主要分为如下的四步: 描述最优解的结构 递归定义最优解的值 按自底向上的方式计算最优解的值 由计算出的结果构造一个最 ...

最新文章

  1. tensorflow 教程 梯度下降法实现线性回归问题
  2. 程序员必须知道的几个Git代码托管平台(转)
  3. Java Comparator排序
  4. NYOJ 303 序号转换 数学题
  5. php中文歌词,详细介绍HTML5使用Audio标签实现歌词同步的效果
  6. sass和less的优缺点
  7. IOS - 本地消息推送
  8. 修改octave的editor的背景颜色
  9. 第一章 对象引论02
  10. Numpy系列(四)常用数学统计函数
  11. linux同步Internet时间
  12. go 导出 html 报告(使用 hero 预编译 html 模板引擎)
  13. [计算机网络】【网络设备】VTP
  14. 快手CEO宿华14年
  15. 学校计算机信息固定资产编号,学校固定资产的分类和编号(仅供参考).doc
  16. 手表无线充电控制芯片方案的原理分析主控SOP8外置挂个AO3400或SI2302
  17. Windows7 Embedded Standard x64更新代码80072EFE解决方法
  18. 再获认可!人大金仓金融信创优秀解决方案推进我国数字金融高质量发展
  19. JAVA社交平台项目第七天 JUC多线程
  20. 关于‘-[UIViewController _loadViewFromNibNamed:bundle:] loaded the “XXXView“ nib but the view outlet wa

热门文章

  1. Mvc项目解决方案分析
  2. 容器set和multiset
  3. python psutils
  4. 实现类似微博、QQ空间等的动态加载
  5. 用Ghostscript API将PDF格式转换为图像格式(C#)
  6. 小巧优美的ORM框架-doodads
  7. (数据科学学习手札61)xpath进阶用法
  8. LeetCode35.搜索插入位置
  9. 浅谈 Android 自定义锁屏页的发车姿势
  10. Effective C++学习笔记——构造/析构/拷贝运算