算法小抄读书笔记1--动态规划

本文深入探讨了动态规划的概念,强调了其两大核心要素——重叠子问题和最优子结构,并通过凑零钱问题展示了动态规划的应用。动态规划是一种优化穷举的方法,通过备忘录减少重复计算,实现高效求解最值问题。文章还提及了递归算法的时间复杂度计算,并列举了动态规划的经典问题。动态规划在解决最优化问题时展现出强大的威力。
摘要由CSDN通过智能技术生成

动态规划

Q:问题的一般形式
A:求最值

Q:你认为动态规划的要素有哪些
A:

    1. 重叠子问题
      - 已经计算过结果的问题不用再计算一次,直接用备忘录/DP table来优化穷举。
    1. 最优子结构
      - 子问题间必须相互独立,说直白点 当前状态做选择不能受之前的路径影响。比如凑零钱问题中零钱的个数要假设无限的。最优子结构是 根据重叠子问题求得最终问题极值 的必要条件。
      - 可以从子问题的最优结果推出更大规模问题的最优结果。
      - 比如 在每个班的第一名中就可以 统计出全校第一名,每个班的第一名就是班级这个子结构的 ‘最优解’。
      - 比如 使用在每个班内的最大分差 统计不出全校的最大分差,这个问题就不符合最优子结构。
    1. 状态转移方程
      - 就是穷举方程。

Q:你认为动态规划的核心是什么
A:动态规划的核心应该是先穷举,和找到重叠子问题后对暴力穷举优化。

Q:经典的动态规划问题有哪些
A: 凑零钱问题:

给你 k 种⾯值的硬币, ⾯值分别为 c1, c2 ... ck , 每种硬
币的数量⽆限, 再给⼀个总⾦额 amount , 问你最少需要⼏枚硬币凑出这个
⾦额, 如果不可能凑出, 算法返回 -1 。
int global_count[2000];
int
coinChange (int coins[3], int amount)
{
    if (global_count[amount] != 0)
	{
	    return global_count[amount];
	}
    std::cout << "amount" << amount << std::endl;
    if (amount < 0)
	{
	    return -1;
	}
    if (amount == 0)
	{
	    return 0;
	}

    int minCount = 65536;
    for (int i = 0; i < 3; i++)
	{
	    int tempCount = coinChange (coins, amount - coins[i]);
	    if (tempCount == -1)
		continue;
	    if (tempCount < minCount)
		{
		    minCount = tempCount;
		}
	}
    if (minCount == 65536)
	return -1;

    global_count[amount] = minCount + 1;
    return minCount + 1;
}

int
main (void)
{
    int coins[3] =
	{ 1, 2, 5 };
    int amount = 1001;
    memset (global_count, 0, sizeof(global_count));
    int count = coinChange (coins, amount);
    std::cout << "count" << count << std::endl;
}
- 1. 暴力递归 : 状态(amount)、选择(coins)、base case(中止条件)
- 2.  带备忘录的递归
- 3. dp数组的迭代解法:从递归变成迭代

Q:一句话概括动态规划
A:聪明的穷举,带备忘录的穷举。

tips: 涉及到递归问题,最好都要画出递归树。对计算复杂度、理清思路非常有帮助。
Q:递归算法的时间复杂度怎么计算?
A:子问题个数乘以解决一个子问题所需要的时间。

Q:未完待续

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值