博客
关于我
简单易懂的背包问题
阅读量:614 次
发布时间:2019-03-13

本文共 2461 字,大约阅读时间需要 8 分钟。

动态规划是一种在计算机科学和数学中广泛应用的算法思想。它通过解决一系列子问题来解决更大的问题。通过让每一个子的结果只用一次,动态规划能够显著降低计算量,避免了重复计算,提高效率。

在国王的金矿问题中,动态规划的思路被清晰地体现出来。国王让大臣们解决更小的问题,并通过比较这些小问题的结果,最终汇总出最优解。每一个大臣的结果代表了一个子问题的解,而通过比较这些解,国王得出了最大的金子数量。

动态规划的关键点

  • 最优子结构:每一个子问题的结果都能够在更大的问题中发挥作用。
  • 子问题重叠:许多子问题具有相似的参数,可以通过记忆化存储这些结果,避免重复计算。
  • 边界:每一个问题都有一个基本的解决方式,例如,如果人数足够开采一个金矿,则只需考虑该金矿的价值。
  • 备忘录(记忆化):保存子问题的解,以便于后续问题的快速查询。
  • 时间分析:动态规划的时间复杂度通常远低于暴力法,特别是在处理较大的参数范围时,动态规划的效率更为突出。
  • 动态规划的应用

    在动态规划中,我们通常会构建一个二维数组来保存子问题的解。这个数组的维度通常由问题中的两个参数决定。例如,在金矿问题中,一个维度代表人数,另一个维度代表已经开采的金矿数量。

    通过递归地分解问题,我们能够逐步填充这个二维数组。每次处理一个问题时,先检查是否已经计算过(通过备忘录),如果已经计算过,就直接返回结果。如果没有计算过,则根据较小的子问题解来计算当前问题。

    代码实现

    以下是一个基于动态规划的代码片段,用于解决类似的背包问题:

    #include 
    #include
    #include
    using namespace std;void init(vector
    &peopleNeed, vector
    &gold, int n, int max_people) { ifstream inputFile("data.txt"); inputFile >> max_people >> n; for(int i = 0; i < n; ++i) { inputPipe >> peopleNeed[i] >> gold[i]; } inputFile.close(); vector
    > maxGold(max_people + 1, vector
    (n + 1, -1)); for(int i = 0; i <= max_people; ++i) for(int j = 0; j <= n; ++j) maxGold[i][j] = -1;}int getMaxGold(int people, int mineNum, const vector
    &peopleNeed, const vector
    &gold, const vector
    > &maxGold) { if(maxGold[people][mineNum] != -1) return maxGold[people][mineNum]; if(mineNum == 0) { if(people >= peopleNeed[0]) return gold[0]; else return 0; } if(people >= peopleNeed[mineNum]) { int option1 = (gold[mineNum] + getMaxGold(people - peopleNeed[mineNum], mineNum - 1, peopleNeed, gold, maxGold)); int option2 = getMaxGold(people, mineNum - 1, peopleNeed, gold, maxGold); return max(option1, option2); } else { return getMaxGold(people, mineNum - 1, peopleNeed, gold, maxGold); } maxGold[people][mineNum] = ret; return ret;}int main() { vector
    peopleNeed; vector
    gold; int max_people, n; init(peopleNeed, gold, n, max_people); cout << getMaxGold(10000, n - 1, peopleNeed, gold, maxGold) << endl; return 0;}

    样例输入输出

    输入:

    100 577 9222 2229 8750 4699 90

    输出:

    133

    总结

    动态规划通过拆分问题、记忆化结果和利用最优子结构,高效地解决了复杂的背包问题。在实际应用中,动态规划不仅提高了效率,还减少了计算的复杂度,使得在面对类似问题时,我们能够快速找到最优解。这也解释了为什么国王能够通过让大臣们分解问题,最终得出最大的金子数量。

    转载地址:http://kszoz.baihongyu.com/

    你可能感兴趣的文章
    简易计算器案例
    查看>>
    在Vue中使用样式——使用内联样式
    查看>>
    Find Familiar Service Features in Lightning Experience
    查看>>
    Explore Optimization
    查看>>
    连接Oracle数据库经常报错?关于listener.ora和tnsnames.ora文件的配置
    查看>>
    解决数据库报ORA-02289:序列不存在错误
    查看>>
    map[]和map.at()取值之间的区别
    查看>>
    成功解决升级virtualenv报错问题
    查看>>
    【SQLI-Lab】靶场搭建
    查看>>
    【Bootstrap5】精细学习记录
    查看>>
    Struts2-从值栈获取list集合数据(三种方式)
    查看>>
    vscode中快速生成vue模板
    查看>>
    参考图像
    查看>>
    *.json: [“usingComponents“][“van-button“] 未找到
    查看>>
    设计模式(18)——中介者模式
    查看>>
    error LNK2019:无法解析的外部符号_imp_CryptAcquireContextA@20
    查看>>
    推荐几篇近期必看的视觉综述,含GAN、Transformer、人脸超分辨、遥感等
    查看>>
    ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED
    查看>>
    BUU-MISC-caesar
    查看>>
    【专题3:电子工程师 之 上位机】 之 【46.QT音频接口】
    查看>>