多年前就听过这个动态规划,最近在复习常用算法的时候才认真学习了一下,发现蛮有意思,和大家安利一波。

定义:

准确来说,动态规划师吧一个复杂问题分解成若干个子问题,并且寻找最优子问题的一种思想,而不是一种特定的算法。

听上去和我们常用的递归有点类似,但是注意:其中子问题的解被重复使用。也就是利用这个特性,我们可以把一个复杂的问题抽象转换成一个简单二维表来进行推演。

动态规划的解题关键在于:

  • 1.根据问题可能性进行拆分。

    从最简单的情况下进行分析,从下往上逐步分析。
  • 2.找到状态转移方程式,保存最优解。

    方程式其实就是在满足某个条件下的递推通项公式,同时也要注意条件范围和边界处理。

最有名的是背包问题:将N种类型的物件放到一个容量为M的背包里面,寻找最优解。

一般来说可以用暴力枚举的方式去算近似最优,但是从空间复杂度和时间复杂度来看使用动态规划更好,因为每一步的结果会保存下来给下一步计算使用,节约了不少时间消耗,最终算法性能极高。

下面举一个典型的例子,来自牛客网的一道"凑整题":

给你六种面额 1、5、10、20、50、100 元的纸币,假设每种币值的数量都足够多,编写程序求组成N元(N为0~10000的非负整数)的不同组合的个数。

仔细分析后发现,这是一个用不同类型的面额组合拼凑固定金额的组合最优解问题。由于N为0 ~ 10000的非负数,我们可以假设N取10来分析。

分析结果如图:

伪代码如下:

if (j - price[i] >= 0) {
Fn(amount) = Fn(j - price[i]) + Fn-1(amount);
} else {
Fn(amount) = Fn-1(amount);
}

其中的Fn函数可以用一个二维数组来实现,第二维为面额个数(即n),第一维度为amount+1种,用于对应的组合数。

用golang实现如下:

func getTheNum(num int) int {
var dp [5][10000]int
moneys = int[...] {1, 5, 10 ,20 , 50, 100}// 面额数组
for i := 0; i < 5; i++ { // 用前i种面额拼凑1rmb的方法数均为1
dp[i][0] = 1
}
for i := 0; i <= num; i++ { // 用1rmb面额拼凑0金额的方法数都为1
dp[0][i] = 1
} for i := 1; i < 5; i++ { // 每一种面额组合递推
for j := 1; j <= num; j++ {
if j - moneys >= 0 { // 当当前金额大于这次循环的面额值,则组合数等于当前i种面额拼凑j金额的组合数+前i+1种面额拼凑j - moneys[i]金额的组合数
dp[i][j] = dp[i-1][j] + dp[i][j - moneys[i]]
} else {
dp[i][j] = dp[i-1][j]
}
}
} return dp[4][num] // 返回最后一项
}

还可以进一步简化,因为二维数组保存的结果在每一次循环判断中都被保存下来了,所以用一维数组也可以保留。改进实现如下:

func SimpleGetNum(num int) int {
var dp [10000]int
moneys = int[...] {1, 5, 10 ,20 , 50, 100}// 面额数组
for i := 0; i <= num; i++ { // 用1rmb面额拼凑0金额的方法数都为1
dp[i] = 1
} for j := 1; j <= 5; j++ {
for i := 1; i <= num; i++ {
if i >= moneys[j] { // 当前面金额大于面额的时候需要计算前i种面额组合出i - moneys[j]的方法数
dp[i] += dp[i - moneys[j]]
}
}
} return dp[num]
}

探索的过程就如同RPG游戏,算法真的是一个很有趣的事情,很多都像精巧的数学问题的代码化。

有趣的动态规划(golang版本)的更多相关文章

  1. 上传golang 版本SDK

    在上传的时候,文件都上传成功了,但是返回的信息里面errcode 404 token 是"".是不是因为我的callbackUrl(随便写的) 写错导致的. 上传golang 版本 ...

  2. Golang版本的rocksdb-对gorocksdb的封装

    rocksdb的优秀特性不用多说,但是它是用c++语言写的,就是这一个特点就把很多人拦住了.虽然rocksdb官方也有Java版本,但是Golang的发展速度让人不容小觑,而且由于golang原生对高 ...

  3. Golang 版本发布 与 TIOBE 排名

    2016年国庆节(10月1日)开始接触 Go 语言,记录一下它的 版本发布 与 TIOBE 排名: Golang 排行榜 月份 版本 排名 备注 2012.03 1.0             201 ...

  4. EasyDarwin开源流媒体服务器Golang版本:服务端录像功能发布

    EasyDarwin开源流媒体服务器(www.easydarwin.org)现在使用Go版本实现了.最新的代码提交,已经支持了推流(或者拉流)的同时进行本地存储. 本地存储的原理,是在推流的同时启动f ...

  5. golang 版本升降之后报错——imports runtime: C source files not allowed when not using cgo or SWIG

    问题: golang 升级或者降级版本之后,执行编译报错如下: package github.com/onsi/ginkgo/ginkgo imports runtime: C source file ...

  6. [原创] linux 下上传 datapoint数据到yeelink 【golang版本】同时上传2个数据点

    /* Create by sndnvaps<sndnvaps@gmail.com> * data: 2015-04-12* upload 2 datapoint to yeelink.ne ...

  7. golang 版本 gearman 试用

    g2 是golang 版的gearman 实现,包含了server (支持leveldb,以及metrics).client 代码.worker 代码 使用上还是很方便的,同时部署也比较简单,结合do ...

  8. TLS示例开发-golang版本

    目录 前言 制作自签名证书 CA 服务器证书相关 客户端证书相关 证书如何验证 在浏览器中导入证书 导入证书 修改域名 golang服务端 目录 main.go 测试 参考 前言 在进行项目总结的时候 ...

  9. [原创] linux 下上传 datapoint数据到yeelink 【golang版本】

    package main /* Create by sndnvaps<sndnvaps@gmail.com> * date : 2015-04-05 * upload datapoint ...

随机推荐

  1. Everything可能泄漏大量电脑敏感资料

    一款好用的文件搜索工具Everything被批露出现重大问题: Everything可以打开http服务,在没有加密的情况下任何外网电脑都可以连接的. 因此,Everything可能泄漏大量电脑敏感资 ...

  2. NOIP模拟13

    上来看了一遍题,发现T2似乎不可做...暴力只给20分怎么玩? T1感觉是要离线处理,但是看了一会发现不会,遂决定先打暴力.然后去把T2 20分拿了,回去看T1,手摸了一下样例,成功推出式子,5分钟码 ...

  3. 『题解』LibreOJ6277 数列分块入门 1

    更好的阅读体验 Portal Portal1: LibreOJ Description 给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,单点查值. Input 第一行输入一个数字 ...

  4. python——自行实现sorted函数

    仿照内建函数sorted,自行实现一个sort函数,能够为列表进行排序 看下面实例的前提是掌握 0.掌握sorted函数的用法.1.函数基本概念.2.函数是如何传参的.3.掌握三元表达式.4.掌握内建 ...

  5. kubernetes实战(二十八):Kubernetes一键式资源管理平台Ratel安装及使用

    1. Ratel是什么? Ratel是一个Kubernetes资源平台,基于管理Kubernetes的资源开发,可以管理Kubernetes的Deployment.DaemonSet.Stateful ...

  6. java property 配置文件管理工具框架,避免写入 property 乱序

    property property 是 java 实现的 property 框架. 特点 优雅地进行属性文件的读取和更新 写入属性文件后属性不乱序 灵活定义编码信息 使用 OO 的方式操作 prope ...

  7. nyoj 277-车牌号 (map, pair, iterator)

    277-车牌号 内存限制:64MB 时间限制:3000ms 特判: No 通过数:9 提交数:13 难度:1 题目描述: 茵茵很喜欢研究车牌号码,从车牌号码上可以看出号码注册的早晚,据研究发现,车牌号 ...

  8. CSS:CSS弹性盒子布局 Flexible Box

    一.简介 flexbox:全称Flexible Box, 弹性盒子布局.可以简单实现各种伸缩性的设计,它是由伸缩容器和伸缩项目组成.任何一个元素都可以指定为flexbox布局.这种新的布局方案在200 ...

  9. 领扣(LeetCode)字母大小写全排列 个人题解

    给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串.返回所有可能得到的字符串集合. 示例: 输入: S = "a1b2" 输出: ["a1 ...

  10. python:类1——类和对象基础

    一.OO = Object Oriented 面向对象 OOP面向对象编程.OOA面向对象分析.OOD面向对象设计 二.属性+方法——>类(数据和函数) class Turtle(): #类名约 ...