算法思想篇(下) | 带你把 动态规划 吃的透透的
Posted 书伟认视界
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法思想篇(下) | 带你把 动态规划 吃的透透的相关的知识,希望对你有一定的参考价值。
动态规划,就是通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
问题:有一个背包,总承载重量是Wkg。现有n个物品,物品重量不全相等,且不可分割。问在不超过背包所能装载重量的前提下,如何让背包中物品的总重量最大?
items=[2,3,2,4]
。
下面具体把这棵递归树画出来看看,其中递归树中的每个节点f(i,cw)表示一种状态,i表示第几个物品,cw表示当前背包中的物品重量。如,f(1,2)表示第一个物品装入背包,总重量是2kg;f(1,0)表示第一个物品不装入背包,背包中此时的重量是0kg。左子树表示装入背包,右子树表示不装入背包。
def bag_dp(items, n, w):
"""
items:物品重量列表
n:物品个数
w:背包允许的最大重量
"""
states = [[0 for i in range(n)] for j in range(w+1)] # 初始化一个状态表
# 后一层状态要根据前一层状态来决策,所以还要初始化第一行
states[0][0] = True
states[0][items[0]] = True
# 依次动态的对每一层进行决策
for i in range(1,n):
# 第i个物品不放入背包
for j in range(w+1):
if states[i-1][j] = True states[i][j]=states[i-1][j]
# 第i个物品放入背包
for j in range(w+1):
if states[i-1][j] = True states[i-1][j] + items[i] = True
# 输出最大不超过背包允许重量的值
for i in range(w,-1,-1):
if states[n-1][i] = True return i
def bag_DP(items, n, w):
states = [0]*(w+1)
states[0] = True
states[items[0]] = True
for i in range(1,n):
for j in range(w-items[i]):
# 若改成(range(w-items[i],-1,-1)),从后往前先计算大数,可避免重复计算问题
if states[j] = True states[j+items[i]] = True
for i in range(w,-1,-1) if states[i] = True retuen 1
状态转移表法
状态转移方程法
台阶问题:有一座高度是 10 级台阶的楼梯,从下往上走,每跨一步只能向上 1 级或者 2 级台阶。要求用程序来求出一共有多少种走法。比如,每次走 1 级台阶,一共走 10 步,这是其中一种走法。我们可以简写成 1,1,1,1,1,1,1,1,1,1。再比如,每次走 2 级台阶,一共走 5 步,这是另一种走法。我们可以简写成 2,2,2,2,2。
def floor(n):
if n<1 return 0
if n==1 return 1
if n==2 return 2
#动态规划过程
a,b,temp = 1,2,0
for i in range(3,n+1):
temp = a + b
a = b
temp = b
return temp
背包问题升级版: 一组重量不全相同的物品,不同价值,且不可分割,满足背包最大重量限制的前提下,背包中物品的总价值最大是多少?
items=[2,3,2,4]
,value=[3,6,4,2]
,
最大背包重量不超过9kg。首先来画递归树来分析一下重复子问题。其中的节点f(i,cw,cv)表示具体的某个状态,i表示第几个物品装还是不装如背包,cw表示当前背包中的总重量,cv表示当前背包中的物品总价值。
def bag_GP2(items, values, n, w):
"""
items:物品重量列表
values:物品价值列表
n:物品个数
w:背包允许的最大重量
"""
# 初始化状态转移表
states = [[-1 for i in range(n)] for j in range(w+1)]
states[0][0] = 0
states[0][items[0]] = values[0]
# 动态规划过程
for i in range(1,n):
# 不选择第i个物品
for j in range(w+1):
if states[i-1][j] >= 0 states[i][j] = states[i-1][j]
# 选择第i个物品
for j in range(W+1):
if states[i-1][j] >= 0:
v = states[i-1][j] + values[i]
if v > states[i-1][j]:
states[i][j+items[i]] = v
# 从最后一行中找最大值
maxValue = -1
for i in range(w+1):
if states[n-1][i] > maxValue maxValue=states[n-1][i]
# pythonic一点的写法:return max(states[n-1])
def bag_DP2(items, values, n, w):
preResult = [-1] * (w+1)
result = [-1] * (w+1)
preResult[0] = 0
preResult[items[0]] = values[0]
for i in range(1,n):
# 不选择第i个物品
for j in range(w+1):
if result[j] < preResult[j]:
result[j] = preResult[j]
# 选择第i个物品
for j in range(w+1):
if preResult[j] >= 0:
result[j+items[i]] = preResult[j]+values[i]
return max(result)
以上是关于算法思想篇(下) | 带你把 动态规划 吃的透透的的主要内容,如果未能解决你的问题,请参考以下文章