动态规划知识点脑图整理:以捡硬币问题为例编写python代码

从数学的视角来看,动态规划是一种运筹学方法,是在多轮决策过程中的最优方法。

那么,什么是多轮决策呢?其实多轮决策的每一轮都可以看作是一个子问题。从分治法的视角来看,每个子问题必须相互独立。但在多轮决策中,这个假设显然不成立。这也是动态规划方法产生的原因之一。

动态规划是候选人参加面试的噩梦,也是面试过程中的难点。以下我根据自己的理解总结了动态规划相关的一些重要概念,便于从宏观上抽象理解这个算法。写的比较简单,如果有不清楚的地方,非常欢迎大家留言讨论。
在这里插入图片描述

下面举一个例子:

题目

有若干硬币排成一个序列,面值依次为[5,1,2,10,6,2],现在规定不能捡相邻的硬币,请问如果捡硬币才能使得捡到的硬币总价值最大

思路

我们需要设计dp表来作为动态规划的数据模型,dp的值显然是硬币的总价值,表格的第一维是第几枚硬币,决策(也就是选择)有两个,第一个是选择第i-1个硬币,第2个是不选择第i-1个硬币,这样我们就可以写出状态转移方程:

dp[i] = max(dp[i-2]+row_coins[i-1],dp[i-1])

注意我们还需要定义边界条件:

dp[0] = 0
dp[1] = row_coins[0]

这样我们就可以得到如下代码求解了,注意我们还需要额外编写traceback回溯来把选择的硬币打印出来。

代码

#通过自定向上的方法来找到最优解
def bottom_up_coins(row_coins):
	dp = [None] * (len(row_coins)+1)
	dp[0] = 0
	dp[1] = row_coins[0]

	for i in range(2,len(row_coins)+1):
		dp[i] = max(dp[i-2]+row_coins[i-1],dp[i-1])

	return dp

c = [5,1,2,10,6,2]
dp = bottom_up_coins(c)

#通过对dp的回溯来反向查找被选择的硬币
def trace_back_coins(c,dp):
	select = []
	i = len(c)
	while i>=1:
		if dp[i] > dp[i-1]:
			select.append(c[i-1])
			i -= 2
		else:
			i -= 1
	return select

print(dp)
print(trace_back_coins(c,dp))

运行结果

在这里插入图片描述
我们看到,用这种方法,很快能求得我们在选取2/10/5这三枚硬币的时候,能得到最优的结果17.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值