数据结构与算法(C++)– 动态规划(Dynamic Programming)
动态规划(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)相关推荐
- 算法导论-动态规划(dynamic programming)
动态规划:通过组合子问题的解来解决整个问题. 动态规划的四个步骤: 1)描述最优解的结构: 2)递归定义最优解的值: 3)按自低向上的方式计算最优解的值(首先找到子问题的最优解,解决子问题,最后找到问 ...
- 算法初探-动态规划(Dynamic Programming)
编程之中接触到很多关于算法的知识,想来整理一番,算是对自己记忆的一个提醒 1.Coin11Problem 问题为:使用最少的三种面值为1,3,5的硬币组合出11元. 重要的是状态以及状态转移方程 d ...
- 数据结构与算法学习⑥(动态规划 题解 背包和打家劫舍问题)
数据结构与算法学习⑥(动态规划 动态规划 1.初识动态规划 1.1.从贪心说起 1.1.1.贪心的特点 1.1.2.贪心的局限性 1.1.3.贪心失效后怎么办 1.1.4.从最优化问题到递归 1.2. ...
- 动态规划 dynamic programming
动态规划dynamic programming June,7, 2015 作者:swanGooseMan 出处:http://www.cnblogs.com/swanGooseMan/p/455658 ...
- 动态规划(Dynamic Programming)的一些事一些情
References <算法导论> 最近在回顾算法的知识,特将一些动态规划的重点记录下来,好让以后自己不要忘记. 基本概念 动态规划(Dynamic Programming,简称为DP,下 ...
- 运筹学状态转移方程例子_动态规划 Dynamic Programming
从运筹学和算法的角度综合介绍动态规划 规划论 Mathematical Programming / Mathematical Optimization In mathematics, computer ...
- 动态规划(Dynamic Programming)与贪心算法(Greedy Algorithm)
文章目录 动态规划算法(Dynamic Programming) 动态规划问题的属性 应用实例:最长公共子序列问题(Longest Common Subsequence, LCS) 贪心算法(Gree ...
- 动态规划|Dynamic Programming
由于最近课设要用动态规划,翻阅资料学习一下. 动态规划 解决复杂问题的方法,把它们分解成更简单的子问题. 一旦我们看到一些例子,这个定义就有意义了.实际上,我们今天只看解问题的例子 解决DP问题的步骤 ...
- [欠驱动机器人]4,动态规划(Dynamic Programming)
目录 前言 控制问题变成优化问题 新增成本(Additive cost) 图搜索的最优控制 连续动力学方程 HJB 方程 求出最小控制 数值求解J 方程逼近与数值迭代 线性方程逼近 网格上的值迭代 连 ...
- 数据结构和算法——用动态规划求解最短路径问题
一.动态规划求解问题的思路 在<算法导论>上,动态规划的求解过程主要分为如下的四步: 描述最优解的结构 递归定义最优解的值 按自底向上的方式计算最优解的值 由计算出的结果构造一个最 ...
最新文章
- tensorflow 教程 梯度下降法实现线性回归问题
- 程序员必须知道的几个Git代码托管平台(转)
- Java Comparator排序
- NYOJ 303 序号转换 数学题
- php中文歌词,详细介绍HTML5使用Audio标签实现歌词同步的效果
- sass和less的优缺点
- IOS - 本地消息推送
- 修改octave的editor的背景颜色
- 第一章 对象引论02
- Numpy系列(四)常用数学统计函数
- linux同步Internet时间
- go 导出 html 报告(使用 hero 预编译 html 模板引擎)
- [计算机网络】【网络设备】VTP
- 快手CEO宿华14年
- 学校计算机信息固定资产编号,学校固定资产的分类和编号(仅供参考).doc
- 手表无线充电控制芯片方案的原理分析主控SOP8外置挂个AO3400或SI2302
- Windows7 Embedded Standard x64更新代码80072EFE解决方法
- 再获认可!人大金仓金融信创优秀解决方案推进我国数字金融高质量发展
- JAVA社交平台项目第七天 JUC多线程
- 关于‘-[UIViewController _loadViewFromNibNamed:bundle:] loaded the “XXXView“ nib but the view outlet wa