老壁灯带你入门动态规划

这篇具有很好参考价值的文章主要介绍了老壁灯带你入门动态规划。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 什么是动态规划

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

从字面意义上来理解,就是走一步看一步,边解决问题,边对问题进行整体规划

其实,动态规划的本质就是将问题拆分为小的子问题,对小问题的一步步解决,小问题渐渐积累为较大的问题,最终就可以解决掉整个问题。

这似乎与递归解决问题的思路很像,但是动态规划一般采用的是迭代的方法。

在解决问题的过程中,我们一般会记录下小问题的解决能带给我们的有效信息,从而利用小问题解决大问题,这样就可以避免对某些问题的重复计算。

动态规划不是什么固定的解题套路,而是提供了一种解题的思路。

动态规划的核心

动态规划的核心在于对两个概念的确定:

1. 当前状态的表示(小问题)

2. 状态之间的递推关系(小问题与较大问题之间的联系)

什么问题可以用动态规划解决

如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划。

例如,求最大值/最小值,可不可行,是不是,方案个数等

 2. 初次遇见动态规划

光是看上面的介绍,似乎有点晕头转向不知所云。

那么,不妨更着博主的学习路径,来看看动态规划到底是怎么回事。

兑换零钱

这是leetcode上的一道题,刷题链接:. - 力扣(LeetCode)

我便是在遇到这道题时,初次见识了动态规划。 

老壁灯带你入门动态规划,动态规划,算法 老壁灯带你入门动态规划,动态规划,算法 老壁灯带你入门动态规划,动态规划,算法

 1. 回溯解法

询问可能性,这让我想到了之前做过的N皇后的问题:C语言解决N皇后问题-CSDN博客

于是我们首先考虑试试回溯的算法。

思路

1. 每次调用函数选择一个硬币,将amount减去该硬币的值之后,传给下一次调用。

2. 依次传递下去,如果某次函数接收到的amount为0,则说明找到了一种可行的组合,此时返回1。

3. 如果某次函数接收到的amount为1,则说明该种组合不可行,此时返回0。

4. 为了避免重复,我们每次传给下一次调用的coins数组都不包括在该硬币位置之前的硬币。

例如,在示例1所给数据下,如果每次传入全部的coins,则会出现诸如2 1 1 1和1 2 1 1的重复情况。 

 代码
int change1(int amount, int* coins, int coinsSize) 
{
    if(amount == 0)
    return 1;
    if(amount < 0||coinsSize <= 0)
    return 0;
    int sum = 0;
    for(int i = 0; i < coinsSize; i++)
    {
        sum += change1(amount - coins[i], coins + i, coinsSize - i);
    }
    return sum;
}
总结

这种解法,虽然极力避免了对重复情况的考虑,但是其递归的本质,还是使其在处理较大数据时会超时。

而且,相比于动态规划,这种解法似乎有点无头苍蝇的感觉,对所有情况进行无差别尝试。

回溯的解法,其运算过程像是树一样,不断展开,每一种情况对应树的一个末梢。

有了这个树状的结构,我们其实可以将每种情况是什么一并打印出来,但是这道题只要求我们求出可行方案的种数。

所以,我们似乎还是做了很多不必要的工作,我们的小问题留下的信息太多了,我们每次计算做的事也太多了。

仔细回顾这道题,我们会发现,如果将我们的思路总结成递归的基本思路,就会是如下这样:

1. 要知道coins组合成amount有多少种方法(),我们首先要知道组合成amount-coins[i]有多少种方法()。

2. 那么。

但是,我们在解决的过程中,不仅把 记录了下来,还将得到其的路径也记录了下来。

而且,在不同的深度中amount-coins[i]的大小可能相同,这也就导致我们还是不可避免地做了很多重复的工作。

于是我在官方的解答中,首次见识了动态规划是如何解决问题的。

2. 动态规划解法

思路

1. 与前面回溯解法总结后的思路相同,我们也要先求得,但是我们只记录在解决这个问题得到的信息中,我们需要的,也就是其值。

2. 状态的表示:我们用一个一维数组来记录每种金额的组合数,元素下标就代表金额。这样,对于每种可能出现的金额(amount-coins[i]),我们就仅会做一次计算。

3. 状态之间的关系:也就是。只要知道较小金额的组合种数,就可以依次递推得到较大金额的组合种数。

4. 结果:我们要求的,其实也就是下标为amount的元素的大小。

5. 下标为0的元素值赋为1,因为得到总金额为0的组合有且仅有一枚硬币都没有的组合。

6. 数组默认初始化为0,这样一来,如果不存在可以组成amount-coins[i]的组合,那么对的贡献就为0。

代码
int change2(int amount, int* coins, int coinsSize)
{
    int dp[amount + 1];
    memset(dp, 0, sizeof(dp));
    dp[0] = 1;
    for(int i = 0; i < coinsSize; i++)
    {
        for(int j = coins[i]; j <= amount; j++)
        {
            dp[j] += dp[j - coins[i]];
        }
    }
    return dp[amount];
}
总结

动态规划的算法通常采用迭代来实现,这不仅解决了递归,回溯的缺陷,而且真正意义上做到了杜绝重复子问题的运算。

并且,在解决问题的过程中,充分利用了子问题留下的有效信息来解决当前问题。

递归时,只能利用自己所在分支的信息,而动态规划可以对全局的信息进行利用。

但是,动态规划的不足就在于其实在不好想到,且没有固定的套路,是考验个人能力的好手段。

3. 尝试自己解决动态规划问题

这是牛客网上的一道题,刷题链接:公共子串计算_牛客题霸_牛客网

 思路

1. 这道题是要我们找两个字符串的公共子串,这使得我会想起之前研究过的kmp算法(从一无所有的角度出发,带你一步步实现kmp算法-CSDN博客)(对这道题不是很重要,不了解也可),这么一想,似乎得到next数组的思想就像是动态规划。

2. 我们依然想用一个数组来存储有效信息,这个数组的下标表示当前的状态(我正在解决哪个问题),其对应的值就是我们要留下的有效信息。

3. 我们用i和j分别指向两个字符串,当所指两个字符匹配成功时,当前公共子串的长度就加1。所以,要想知道当前公共子串的长度,我们就要知道在这两个字符匹配成功之前公共子串的长度。

4. 那么,这道题用一维数组似乎无法很好地表示当前的状态,因为我们要知道匹配之前公共子串的长度,那么其对应的i和j就都需要能表示出来,我们才能找到它。

5. 状态的表示:于是我们采用二维数组(dp[][])来定义当前状态,元素的下标分别为i和j,表示当前公共子串的末尾在两个字符串中分别在第i个和第j个位置上。

6. 状态之间的关系:如果当前两个字符配对成功则dp[i][j] = dp[i-1][j-1] + 1;如果匹配失败,则dp[i][j] = 0。

7. 结果:我们定义一个变量maxLen来记录目前最长的公共子串长度,如果某位置上dp[i][j] > maxLen,则maxLen = dp[i][j]。将每个位置的公共子串都检查完之后maxLen即是要求结果。

代码

#include <stdio.h>
#include <string.h>

int main() 
{
    char arr1[151] = {0};
    char arr2[151] = {0};
    scanf("%s", arr1);
    scanf("%s", arr2);
    int len1 = strlen(arr1);
    int len2 = strlen(arr2);
    int dp[len1+1][len2+1];
    int maxLen = 0;

    memset(dp, 0, sizeof(dp));
    for(int i = 1; i <= len1; i++)
    {
        for(int j = 1; j <= len2; j++)
        {
            dp[i][j] = arr1[i-1] == arr2[j-1] ? dp[i-1][j-1] + 1 : 0;
            maxLen = maxLen > dp[i][j] ? maxLen : dp[i][j];
        }
    }

    printf("%d\n", maxLen);
    
    return 0;
}

总结

动态规划是很值得学习的东西,也是需要费力攻克的难关,绝不是看一两篇文章就能完全掌握的。

本文章只是带领读者初步了解动态规划这种解题思想,能够入门,方便进行更加深入的学习。

博主也是刚刚接触到这类题型,顿时感到未来的路还很长,希望在了解更多之后还有机会分享动态规划学习的文章。

接下来,可以通过背包问题,进行更加深入地学习。文章来源地址https://www.toymoban.com/news/detail-850574.html

到了这里,关于老壁灯带你入门动态规划的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【算法入门】浅谈动态规划

    关于动态规划的定义,网上有很多,但对于初学者,看了定义之后,多少会有点懵,接下来我打算用俩到三个例题来引入动态规划的定义,我将动态规划分为动态和规划俩部分,动态说明它是变化的,规划说明它是从前到后的,所以综合下来就是后面的由前面或者说受前面影

    2024年04月12日
    浏览(40)
  • 算法套路十三——动态规划DP入门

    动态规划和递归都是通过将大问题分解为较小的子问题来解决问题。它们都可以用来解决具有重叠子问题和最优子结构特性的问题。 递归是一种自顶向下的方法, 它从原始问题开始 ,递归地将问题分解为较小的子问题dfs(i)—— dfs(i)代表的是从第i个状态开始进行递归求解能

    2024年02月15日
    浏览(57)
  • 【算法思考记录】动态规划入门!力扣2606. 找到最大开销的子字符串【Python3、动态规划】

    原题链接 动态规划(Dynamic Programming,简称 DP)是一种通过将原问题分解为相互重叠的子问题并只解决一次的方法来解决问题的算法优化技术。动态规划通常用于优化递归问题,通过存储子问题的解来避免重复计算,从而显著提高算法的效率。 动态规划的基本思想是将原问题

    2024年02月03日
    浏览(42)
  • 猿创征文 |【算法面试入门必刷】动态规划-线性dp(一)

    📦个人主页:一二三o-0-O的博客 🏆技术方向:C/C++客户端资深工程师(直播+音视频剪辑) 👨‍💻作者简介:数据结构算法与音视频领域创作者 📒 系列专栏:牛客网面试必刷 📣专栏目标:帮助伙伴们通过系统训练,掌握数据结构与算法,收获心仪Offer 📝推荐一个找工作

    2024年02月03日
    浏览(63)
  • 猿创征文 |【算法面试入门必刷】动态规划-线性dp(四)

    📦个人主页:一二三o-0-O的博客 🏆技术方向:C/C++客户端资深工程师(直播+音视频剪辑) 👨‍💻作者简介:数据结构算法与音视频领域创作者 📒 系列专栏:牛客网面试必刷 📣专栏目标:帮助伙伴们通过系统训练,掌握数据结构与算法,收获心仪Offer 📝推荐一个找工作

    2024年02月02日
    浏览(35)
  • 数据结构与算法之美学习笔记:41 | 动态规划理论:一篇文章带你彻底搞懂最优子结构、无后效性和重复子问题

    本节课程思维导图: 今天,我主要讲动态规划的一些理论知识。学完这节内容,可以帮你解决这样几个问题:什么样的问题可以用动态规划解决?解决动态规划问题的一般思考过程是什么样的?贪心、分治、回溯、动态规划这四种算法思想又有什么区别和联系? 什么样的问

    2024年02月02日
    浏览(64)
  • 【带你了解动态规划】

    🔥博主:程序员不想YY啊🔥 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家💫 🤗点赞🎈收藏⭐再看💫养成习惯 🌈希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共同学习、交流进步!🌈 动态规划是一种算法思想,主要用于求解具有重叠子问题和

    2024年04月09日
    浏览(54)
  • 动态规划(带你了解 原理 实践)

    目录 引言 一、动态规划的基本概念 二、动态规划的应用 1. 背包问题 2. 最短路径问题 3. 0-1背包问题的变种 4. 字符串匹配与编辑距离 5. 金融投资组合优化 6. 生产调度问题 7. 项目管理中的资源分配 三、动态规划算法的优缺点 优点 1 效率高 2 通用性强 缺点: 1 空间复杂度较高

    2024年03月19日
    浏览(48)
  • 一篇文章带你搞懂动态规划(由暴力递归到动态规划)

    ”动态规划“ 的过程相当于 记忆化搜索 , 即在普通 递归 的过程中用二维数组进行记忆化存储一些状态结果, 从而避免重复的计算(剪枝)。 举一个简单的例子:在 递归法 求解 斐波那契 数列的过程中, 就进行了多次的 重复计算 , 而动态规划相当于是对已经计算的状态

    2024年02月20日
    浏览(54)
  • 动态规划太难了?是你没有找对方法,四题带你搞懂动态规划!

    💯 博客内容:动态规划刷题 😀 作  者:陈大大陈 🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信! 💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘 目录  一.91. 解码方法 - 力扣(LeetC

    2024年02月07日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包