三个例子理解动态规划(背包(基本、优化时间、优化空间),币值最大化,找零问题)

本文深入探讨动态规划的概念,通过币值最大化、找零问题和不同类型的背包问题(基本、记忆化、优化空间)来阐述动态规划的解决思路。通过递归与动态规划的效率比较,强调了动态规划在重复子问题求解中的优势,并提供了相关代码参考链接。
摘要由CSDN通过智能技术生成

动态规划综述

  • 可分为多个相关子问题,子问题的解可以被重复使用(下方例子中是F数组与value数组来保留子问题解的),这也是相比于递归暴力求解效率提高的关键,下方前两个例子会简单比较效率,第二个例子由于数据不具代表性,所以有所差异
  • 动态规划的关键就是如何根据条件从上一个子问题的最优解到该现状的途径(写出递推关系)
  • 然后该途径会有很多种再根据问题通过min或max求得哎现状的最优解,该现状当然也又有可能出现在之后现状的子问题当中
  • 写出初始条件
  • (之前自己理解的误区)在理解中不要仅仅注意到递推关系,比如背包问题中之前理解错了是总是感觉包括第i件物品的组合肯定肯定比不包括第i件物品的组合的总价值大,这种理解的错法在于没有真正理解到动态规划的自下而上,而仅仅看到了递推关系,实际上这里F(i ,j),变的不仅仅是i,还有j,相当于你不包括第i件物品,那么你就有更多的空间去选择其他的,总之就是包含第i件与不包含第i件的前一子组合的子组合是不同的。(之前初次接触的背包问题的误区,这次系统看了下动态规划,欢迎交流)
  • 上面看不懂?直接看代码!

参考书籍:《算法分析与设计》

参考博客: https://blog.csdn.net/qq_34178562/article/details/79959380

github(jupyter源码): https://github.com/Justin3go/BasicComputerNotes/tree/main/算法分析与设计

币值最大化问题

问题描述:给定一排硬币,这些整数不一定两两相同。使得在其原始位置互不相邻的条件下,所选硬币金额最大。

算法思想

  • 包括最后一枚的:c_n + F(n-2)
  • 不包括最后一枚的:F(n-1)

动态规划实现

def CoinRow1(coins):
	F = [0]
	F.append(coins[0])
	for i in range(1, len(coins)):
		F.append(max(coins[i] + F[i-1], F[i])) 

	return F[len(coins)]

test_coin = [5, 1, 2, 10, 6, 2]
CoinRow1(test_coin)
17

递归实现

def CoinRow2(coins, i):
	if i == 0:
		return 0
	if i == 1:
		return coins[0]
	return max((coins[i] + CoinRow2(coins, i - 2)), CoinRow2(coins, i - 1))

test_coin = [5, 1, 2, 10, 6, 2]
CoinRow2(test_coin, len(test_coin)-1)

17

效率比较

import matplotlib.pyplot as plt
import numpy as np
import time

cost_time_log1 = []
cost_time_log2 = []
for i in range(1, 6):
    print(
        "**********************************第%s数据规模********************************"
        % i)
    # 数据生成
    test_coins = list(np.random.randint(0, 1000, i * 6))
    t1 = time.time()
    print("CoinRow1", CoinRow1(test_coins))
    t2 = time.time()
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值