今天要讲的动态规划,其面对的问题通常是无法一蹴而就,需要把复杂的问题分解成简单具体的小问题,然后通过求解简单问题,去推出复杂问题的最终解。
形象的理解就是为了推倒一系列纸牌中的第100张纸牌,那么我们就要先推倒第1张,再依靠多米诺骨牌效应,去推倒第100张。
实例讲解
斐波拉契数列是这样一个数列:1, 1, 2, 3, 5, 8, 。。. 除了第一个和第二个数字为1以外,其他数字都为之前两个数字之和。现在要求第100个数字是多少。
这道题目乍一看是一个数学题,那么要求第100个数字,很简单,一个个数字算下去就是了。假设F(n)表示第n个斐波拉契数列的数字,那么我们易得公式F(n) = F(n - 1) + F(n - 2),n 》= 2,下面就是体力活。当然这道题转化成代码也不是很难,最粗暴的解法如下:
func Fib() -》 Int {
var prev = 0
var curr = 1
for _ in 1 。。《 100 {
var temp = curr
curr = prev + curr
prev = temp
}
return curr
}
用动态规划怎么写呢?首先要明白动态规划有以下几个专有名词:
1. 初始状态,即此问题的最简单子问题的解。在斐波拉契数列里,最简单的问题是,一开始给定的第一个数和第二个数是几?自然我们可以得出是1
2. 状态转移方程,即第n个问题的解和之前的 n - m 个问题解的关系。在这道题目里,我们已经有了状态转移方程F(n) = F(n - 1) + F(n - 2)
所以这题要求F(100),那我们只要知道F(99)和F(98)就行了;想知道F(99),我们只要知道F(98)和F(97)就行了;想要知道F(98),我们需要知道F(97)和F(96)。。。,以此类推,我们最后只要知道F(2)和F(1)的值,就可以推出F(100)。而F(2)和F(1)正是我们所谓的初始状态,即 F(2) = 1,F(1) =1。所以代码如下:
func Fib(n: Int) -》 Int {
// 定义初始状态
guard n 》 0 else {
return 0
}
if n == 1 || n == 2 {
return 1
}
// 调用状态转移方程
return Fib(n - 1) + Fib(n - 2)
}
print(Fib(100))
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !