有趣的动态规划(golang版本)
多年前就听过这个动态规划,最近在复习常用算法的时候才认真学习了一下,发现蛮有意思,和大家安利一波。
定义:
准确来说,动态规划师吧一个复杂问题分解成若干个子问题,并且寻找最优子问题的一种思想,而不是一种特定的算法。
听上去和我们常用的递归有点类似,但是注意:其中子问题的解被重复使用。也就是利用这个特性,我们可以把一个复杂的问题抽象转换成一个简单二维表来进行推演。
动态规划的解题关键在于:
- 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版本)的更多相关文章
- 上传golang 版本SDK
在上传的时候,文件都上传成功了,但是返回的信息里面errcode 404 token 是"".是不是因为我的callbackUrl(随便写的) 写错导致的. 上传golang 版本 ...
- Golang版本的rocksdb-对gorocksdb的封装
rocksdb的优秀特性不用多说,但是它是用c++语言写的,就是这一个特点就把很多人拦住了.虽然rocksdb官方也有Java版本,但是Golang的发展速度让人不容小觑,而且由于golang原生对高 ...
- Golang 版本发布 与 TIOBE 排名
2016年国庆节(10月1日)开始接触 Go 语言,记录一下它的 版本发布 与 TIOBE 排名: Golang 排行榜 月份 版本 排名 备注 2012.03 1.0 201 ...
- EasyDarwin开源流媒体服务器Golang版本:服务端录像功能发布
EasyDarwin开源流媒体服务器(www.easydarwin.org)现在使用Go版本实现了.最新的代码提交,已经支持了推流(或者拉流)的同时进行本地存储. 本地存储的原理,是在推流的同时启动f ...
- 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 ...
- [原创] linux 下上传 datapoint数据到yeelink 【golang版本】同时上传2个数据点
/* Create by sndnvaps<sndnvaps@gmail.com> * data: 2015-04-12* upload 2 datapoint to yeelink.ne ...
- golang 版本 gearman 试用
g2 是golang 版的gearman 实现,包含了server (支持leveldb,以及metrics).client 代码.worker 代码 使用上还是很方便的,同时部署也比较简单,结合do ...
- TLS示例开发-golang版本
目录 前言 制作自签名证书 CA 服务器证书相关 客户端证书相关 证书如何验证 在浏览器中导入证书 导入证书 修改域名 golang服务端 目录 main.go 测试 参考 前言 在进行项目总结的时候 ...
- [原创] linux 下上传 datapoint数据到yeelink 【golang版本】
package main /* Create by sndnvaps<sndnvaps@gmail.com> * date : 2015-04-05 * upload datapoint ...
随机推荐
- Everything可能泄漏大量电脑敏感资料
一款好用的文件搜索工具Everything被批露出现重大问题: Everything可以打开http服务,在没有加密的情况下任何外网电脑都可以连接的. 因此,Everything可能泄漏大量电脑敏感资 ...
- NOIP模拟13
上来看了一遍题,发现T2似乎不可做...暴力只给20分怎么玩? T1感觉是要离线处理,但是看了一会发现不会,遂决定先打暴力.然后去把T2 20分拿了,回去看T1,手摸了一下样例,成功推出式子,5分钟码 ...
- 『题解』LibreOJ6277 数列分块入门 1
更好的阅读体验 Portal Portal1: LibreOJ Description 给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,单点查值. Input 第一行输入一个数字 ...
- python——自行实现sorted函数
仿照内建函数sorted,自行实现一个sort函数,能够为列表进行排序 看下面实例的前提是掌握 0.掌握sorted函数的用法.1.函数基本概念.2.函数是如何传参的.3.掌握三元表达式.4.掌握内建 ...
- kubernetes实战(二十八):Kubernetes一键式资源管理平台Ratel安装及使用
1. Ratel是什么? Ratel是一个Kubernetes资源平台,基于管理Kubernetes的资源开发,可以管理Kubernetes的Deployment.DaemonSet.Stateful ...
- java property 配置文件管理工具框架,避免写入 property 乱序
property property 是 java 实现的 property 框架. 特点 优雅地进行属性文件的读取和更新 写入属性文件后属性不乱序 灵活定义编码信息 使用 OO 的方式操作 prope ...
- nyoj 277-车牌号 (map, pair, iterator)
277-车牌号 内存限制:64MB 时间限制:3000ms 特判: No 通过数:9 提交数:13 难度:1 题目描述: 茵茵很喜欢研究车牌号码,从车牌号码上可以看出号码注册的早晚,据研究发现,车牌号 ...
- CSS:CSS弹性盒子布局 Flexible Box
一.简介 flexbox:全称Flexible Box, 弹性盒子布局.可以简单实现各种伸缩性的设计,它是由伸缩容器和伸缩项目组成.任何一个元素都可以指定为flexbox布局.这种新的布局方案在200 ...
- 领扣(LeetCode)字母大小写全排列 个人题解
给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串.返回所有可能得到的字符串集合. 示例: 输入: S = "a1b2" 输出: ["a1 ...
- python:类1——类和对象基础
一.OO = Object Oriented 面向对象 OOP面向对象编程.OOA面向对象分析.OOD面向对象设计 二.属性+方法——>类(数据和函数) class Turtle(): #类名约 ...