动态规划法(九)想要更多例子?
本文将会介绍三个用动态规划法解决的例子,分别是:
- 楼梯台阶问题
- 二项式系数求解
- 最大乘积子数组问题
楼梯台阶问题
一个n阶的楼梯,一个婴儿每次爬一阶或两阶,试问一共有多少种办法爬完楼梯。
设f(n)为该问题的解,考虑最后一次的爬法,若最后一次爬一阶,则前面n-1阶楼梯有f(n-1)种办法,若最后一次爬两阶,则前面n-2阶楼梯有f(n-2)种办法,因此:
f(1)=1,f(2)=2,f(3)=3,….该数列为斐波那契数列,可以参考博客 动态规划法(一)从斐波那契数列谈起用动态规划法进行求解。
一个n阶的楼梯,一个婴儿每次爬一阶或两阶或三阶台阶,试问一共有多少种办法爬完楼梯。
同上面的解法一样,有:
其中,f(1)=1,f(2)=2,f(3)=4. 可以参考博客 动态规划法(二)找零钱问题用动态规划法进行求解。
二项式系数求解
对于二项式系数,有如下等式:
再结合 C0n=1,C1n=nCn0=1,Cn1=n对该问题用动态规划法进行求解,本质上这也是一个递归关系式。Python代码如下:
import numpy as np def binomial(n, k): if k == 0: return 1 elif k == 1: return n else: table = np.array([[0] * (k + 1)] * n, dtype='int64') for i in range(n): table[i, 0] = 1 table[i, 1] = i + 1 for i in range(n): for j in range(2, k+1): if i+1 < j: table[i, j] = 0 else: table[i, j] = table[i-1, j] + table[i-1, j-1] return table[n-1, k] t = binomial(50, 10) print(t)
最大乘积子数组问题
所谓的最大乘积子数组问题,指的是:给定一个数组A,寻找A的乘积最大的非空连续子数组。比如,数组 A = [-2, -3, 4], 最大乘积子数组应为A,其乘积为24。
在博客动态规划法(八)最大子数组问题(maximum subarray problem)中,我们已经用动态规划法解决了最大子数组问题。对于最大乘积子数组问题,我们也可以类似地用动态规划法解决。但是,对于A中元素均为正数的情形,可以有更简单的方法。
首先对A中元素去对数,则原问题等价于最大子数组问题,找出最大和后,再用指数作用,就能得到A中元素均为正数的最大乘积子数组问题的解。其Python代码如下:
from math import log2, pow # using dynamic programming to slove maximum subarray problem def DP_maximum_subarray(old_arr): # 对原数组取底为2的对数 arr = [log2(x) for x in old_arr] # 对新数组求解最大子数组问题 # 并求出该子数组的开始坐标(begin_index)和结束坐标(end_index) t = len(arr) MS = [0]*t # 初始化MS数组 MS[0] = arr[0] # 动态规划法的初始值 # 动态规划法的子结构 for i in range(1, t): MS[i] = max(MS[i-1]+arr[i], arr[i]) # 求解该子数组的开始坐标(begin_index)和结束坐标(end_index) end_index = MS.index(max(MS)) begin_index = end_index sum = arr[end_index] while abs(sum- max(MS)) > pow(10, -5): begin_index -= 1 sum += arr[begin_index] return begin_index, end_index, pow(2, max(MS)) a = [1/2, 4, 1/2, 16, 1/8, 32, 2, 1/16] begin_index, end_index, max_product = DP_maximum_subarray(a) print([begin_index, end_index, max_product])
输出结果为:
[1, 6, 256.0]
最大乘积子数组问题的最大乘积为256,子数组开始坐标为1,结束坐标为6,因此子数组为[4, 1/2, 16, 1/8, 32, 2]。
注意:本人现已开通两个微信公众号: 因为Python(微信号为:python_math)以及轻松学会Python爬虫(微信号为:easy_web_scrape), 欢迎大家关注哦~~

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java并发编程笔记之Unsafe类和LockSupport类源码分析
一.Unsafe类的源码分析 JDK的rt.jar包中的Unsafe类提供了硬件级别的原子操作,Unsafe里面的方法都是native方法,通过使用JNI的方式来访问本地C++实现库。 rt.jar 中 Unsafe 类主要函数讲解, Unsafe 类提供了硬件级别的原子操作,可以安全的直接操作内存变量,其在 JUC 源码中被广泛的使用,了解其原理为研究 JUC 源码奠定了基础。 首先我们先了解Unsafe类中主要方法的使用,如下: 1.long objectFieldOffset(Field field) 方法:返回指定的变量在所属类的内存偏移地址,偏移地址仅仅在该Unsafe函数中访问指定字段时使用。如下代码使用unsafe获取AtomicLong中变量value在AtomicLong对象中的内存偏移,代码如下: static { try { valueOffset = unsafe.objectFieldOffset(AtomicLong.class.getDeclaredField("value")); } catch (Exception ex) { throw new ...
- 下一篇
Java 学习(07)--面向对象常见问题
1.有5家衣服专卖店,每家最多购买3件。用户可以选择离开,可以买衣服。最后打印总共买了几件衣服。 代码: //有5家衣服专卖店,每家最多购买3件。用户可以选择离开,可以买衣服。最后打印总共买了几件衣服。 import java.util.Scanner; public class BuyClothes{ private static int number = 0;//存储总购买量 public void setNumber(int a){ number = number+a; } public int GetNumber(){ return number; } public static void main(String[] args){ int name;//输出商店序号 shop s=new shop(); for(name = 1 ; name<6 ; name++){ System.out.println("欢迎光临第" + name + "家专卖店"); s.ask(); } System.out.println("总共买了" + number + "件衣服");//输...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS关闭SELinux安全模块
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16