算法——动态规划

it2022-05-05  145

动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。

下面我们通过具体的问题去学习应用动态规划。

动态规划之Fib数列问题

问题描述:

有一个小孩上楼梯,共有N阶楼梯,小孩一次可以上1阶或2阶。走到N阶楼梯,一共有多少种走法?

问题分析:

自顶向下分析方式:

爬到第N阶楼梯,一共只有2种情况(全划分,加法原理),第一种是从第N-1阶爬1阶楼梯到第N阶;第二种是从第N-2阶爬2阶楼梯到第N阶。

故可得到:way(N)=way(N-1)+way(N-2)

下面用Python实现形如Fib数列的问题,代码如下:

# 动态规划 先解决小数据量的 再层层递推的解决大数据量级的问题 时间复杂度O(n) def fib2(n): memo = [-1 for x in range(n+1)] memo[0] = 0 memo[1] = 1 for i in range(2, n+1): memo[i] = memo[i - 1] + memo[i - 2] return memo[n] if __name__ == '__main__': n = 10 print(fib2(n))

输出结果如下:

 


任务安排问题

 问题描述:

假如有一天老板给你安排了一系列任务供你选择,每个任务的收益是不同的,并且在选择了一个任务之后,在该任务所执行的时间段内不能选择其他任务,也就是所选择的任务时间不能有冲突,这时你该如何去选择任务,可以使你的收益达到最大?假如任务安排如下图所示,红色数字代表每个任务的收益:

 

问题分析:

对于每一个任务只有两种情况,选择或者不选它。试着倒着分析该问题,选择第8个任务时,就还可以选择第5个任务,最大收益就是他俩的收益和;或者不选择第5个任务,可以选择第4个任务,然后再选择第1个任务,他俩也可以不选择,又是另外的情况。不选择第8个任务时,选择第7个任务,再选择后面的任务;也可能不选择第7 个而选择第6个……

那么可以作如下总结:

i 表示第i个任务,opt表示最大收益,表示第i个任务的收益,prev[i]表示第i个任务之前可以执行的任务。

当选择第 i 个任务时,最大收益为:

当不选择第 i 个任务时,最大收益为: 

可以总结出下表:

iprev[i]opt[i]10520530841950962973108513

 

下面我们以该例子为例用Python实现任务安排问题,代码如下:

# 数组arr存储的是每个任务的收益; arr = [0, 5, 1, 8, 4, 6, 3, 2, 4] #数组prev存储的是指定任务之前可以执行的任务 prev = [0, 0, 0, 0, 1, 0, 2, 3, 5] def dp_opt(arr): #计算任务的长度 len_arr = len(arr) # 存储执行到每个任务可以获得的最优解; opt = [0 for i in range(len_arr)] opt[0] = 0 opt[1] = arr[1] for i in range(2, len(arr)): # 不选择做这个任务的最优解; A = opt[i - 1] # 选择做这个任务的最优解; B = arr[i] + opt[prev[i]] opt[i] = max(A, B) return opt[-1] print(dp_opt(arr))

输出结果为最大收益,如下:


不相邻数最大和 

问题描述:

给定数组A=[1,2,4,1,7,8,3],求出数组A中互不相邻的数的最大和。 例如:如果选择了8,则不能选择7和3,在本例中最大的和为1+4+7+3=15 

问题关键:不能选相邻的数字  选择的数字和最大max

该问题分析同上面的任务安排问题分析,也可做出类似的总结:

i 为所选择的数字的索引值,那么,

当选择第 i 个数字时,最大和为:

当不选择第 i 个数字时,最大和为:

 

以该例子为例用Python实现不相邻数最大和问题,代码如下:

arr = [1, 2, 4, 1, 7, 8, 3] def max_sum(arr): len_arr = len(arr) opt = [0 for i in range(len_arr)] opt[0] = 1 opt[1] = arr[1] for i in range(2, len(arr)): not_choice = opt[i - 1] choice = arr[i] + opt[i - 2] opt[i] = max(not_choice, choice) return opt[-1] print(max_sum(arr))

输出为计算的最大的和,结果为:


最新回复(0)