首页 > 编程语言 >C++语法10:C++实现0-1背包问题的动态规划解法

C++语法10:C++实现0-1背包问题的动态规划解法

时间:2024-07-24 22:55:18浏览次数:17  
标签:10 背包 C++ 问题 解法 物品 动态 规划 dp

动态规划(Dynamic Programming):解锁复杂问题的钥匙

在算法设计与分析的广阔领域中,动态规划(Dynamic Programming, DP)无疑是一把锋利的剑,用于斩断复杂问题中缠绕的荆棘。它通过将大问题分解为小问题,并存储子问题的解来避免重复计算,从而高效地解决了一系列看似无解的难题。本文将从动态规划的用途、用法、好处以及具体示例四个方面,深入探讨这一强大的算法思想。

一、动态规划的用途

动态规划广泛应用于计算机科学、经济学、生物学等多个领域,特别是在处理最优化问题时表现出色。其典型应用场景包括但不限于:

  • 最短路径问题:如Dijkstra算法和Floyd-Warshall算法,都运用了动态规划的思想来寻找图中两点间的最短路径。
  • 背包问题:包括0-1背包、完全背包等,通过动态规划可以高效解决在给定容量下如何选择物品使得总价值最大的问题。
  • 序列问题:如最长公共子序列(LCS)、最长递增子序列(LIS)等,动态规划能够有效找出序列中的最优子序列。
  • 最优决策过程:在决策过程中,每一步的选择都依赖于之前的状态,动态规划通过构建状态转移方程来找到最优决策序列。
二、动态规划的用法

动态规划的基本步骤通常包括:

  1. 定义状态:首先明确问题的状态表示,即如何用一个或多个变量来刻画当前问题的状态。
  2. 状态转移方程:根据问题的性质,推导出状态之间的转移关系,即如何从旧状态推导出新状态。
  3. 初始化:为状态数组或表格设置初始值,这通常是问题的边界条件或特殊情况。
  4. 填表:按照某种顺序(通常是自底向上或从左到右)计算所有状态的值。
  5. 答案提取:根据问题的要求,从状态数组或表格中提取最终答案。
三、动态规划的好处
  1. 高效性:通过避免重复计算,动态规划显著提高了算法的效率,特别是对于具有重叠子问题特性的问题。
  2. 系统性:动态规划提供了一个结构化的方法来解决问题,使得问题的解决过程更加清晰和有条理。
  3. 可扩展性:动态规划的思想可以灵活应用于多种类型的问题,只需调整状态定义和状态转移方程即可。
  4. 易于理解:虽然动态规划问题的初始理解可能较为困难,但一旦掌握了其基本原理,就能轻松应对各种变体。
四、示例:0-1背包问题

问题描述:给定n种物品和一个容量为W的背包,物品i的重量是wt[i],其价值为val[i],每种物品只有一件。求解将哪些物品装入背包可使这些物品的总价值最大。

动态规划解法

  1. 定义状态:dp[i][j]表示前i件物品放入容量为j的背包中所能获得的最大价值。
  2. 状态转移方程:对于第i件物品,我们有两种选择:放或不放。因此,dp[i][j] = max(dp[i-1][j], dp[i-1][j-wt[i]] + val[i]),其中dp[i-1][j]表示不放第i件物品时的最大价值,dp[i-1][j-wt[i]] + val[i]表示放第i件物品时的最大价值。
  3. 初始化:dp[0][j] = 0(没有物品时,无论背包容量多大,价值都为0);dp[i][0] = 0(背包容量为0时,无论有多少物品,价值都为0)。
  4. 填表:从dp[1][1]开始,按照顺序填充dp数组。
  5. 答案提取:dp[n][W]即为所求的最大价值。

通过上述示例,我们可以看到动态规划在解决复杂问题时的强大力量。它不仅提高了算法的效率,还使得问题的求解过程更加系统化和易于理解。

#include <iostream>  
#include <vector>  
#include <algorithm> // 用于max函数  
  
using namespace std;  
  
// 0-1背包问题的C++实现  
int knapsack(int W, vector<int>& weights, vector<int>& values, int n) {  
    // 创建一个一维DP数组,dp[j]表示容量为j的背包能装的最大价值  
    vector<int> dp(W + 1, 0);  
  
    // 遍历所有物品  
    for (int i = 0; i < n; ++i) {  
        // 逆序遍历背包容量,防止一个物品被多次选择  
        for (int j = W; j >= weights[i]; --j) {  
            // 更新dp[j]为包含当前物品i或不包含当前物品i的最大值  
            dp[j] = max(dp[j], dp[j - weights[i]] + values[i]);  
        }  
    }  
  
    // 返回背包能装的最大价值  
    return dp[W];  
}  
  
int main() {  
    // 示例:背包容量W=50,4个物品的重量和价值  
    int W = 50;  
    vector<int> weights = {10, 20, 30, 40};  
    vector<int> values = {60, 100, 120, 150};  
    int n = weights.size(); // 物品数量  
  
    // 调用函数并输出结果  
    cout << "Maximum value that can be put in a knapsack of capacity " << W << " is " << knapsack(W, weights, values, n) << endl;  
  
    return 0;  
}

在这个例子中,我们将使用一维动态规划数组来优化空间复杂度,因为传统的二维DP数组在第一维上经常是冗余的(给定当前背包容量和物品,我们只需要知道前一个物品和当前容量的信息)。

这段代码首先定义了一个knapsack函数,它接受背包的容量W、物品的重量数组weights、物品的价值数组values以及物品的数量n作为输入。然后,它使用一维动态规划数组dp来存储每个背包容量下的最大价值。通过两层循环(外层遍历物品,内层逆序遍历背包容量),我们根据当前物品是否放入背包来更新dp数组。最后,函数返回dp[W],即背包容量为W时的最大价值。

五、总结

通过上面的C++实现,我们深入理解了动态规划在解决0-1背包问题中的强大作用。动态规划不仅优化了计算过程,减少了不必要的重复计算,还通过一维数组的巧妙应用进一步节省了空间复杂度。这种方法不仅适用于0-1背包问题,还可以推广到许多其他具有最优子结构和重叠子问题特性的问题上。希望这篇文章能帮助读者掌握动态规划的基本思想和应用技巧,在未来的算法学习和实践中更加游刃有余。继续探索吧,算法的世界等待着每一位热爱编程的你!

最后,都看到这里了,留下一个免费的赞和关注呗~跪谢~

关注我,C++语法中的其它文章同样精彩!

这是我本系列的最后一篇文章了,感谢大家对我的支持!

马上我会出一部新的专辑,希望大家能关注!

标签:10,背包,C++,问题,解法,物品,动态,规划,dp
From: https://blog.csdn.net/LUSIYUANGASTER/article/details/140674582

相关文章

  • Linux多线程C/C++
    文章目录前言一、线程1.线程的使用2.线程相关函数1.pthread_create()线程创建函数2.pthread_join()线程回收函数3.pthread_exit()线程退出函数4.pthread_detach()线程分离函数二、线程的同步与互斥1.互斥锁(Mutex)2.读写锁(Read-WriteLock)3.条件变量(ConditionVa......
  • c++11(3): 类型推导与智能指针
    41.两个右尖括号>在模板中不再被判定为右移,需要右移需要加圆括号()42.auto类型推导,编译时推导inta=1;autob=a;//b的类型为int1):auto不能作函数形参类型2):auto不能对结构体中的肥静态成员进行推导3):auto不能声明数组4):auto不能在实例化模板时作为......
  • 2024暑假集训测试10
    前言比赛链接。这回挂的比较少,就T2唐了太长时间导致T4暴力没打完挂了\(60\),不过T4暴力给的非常多,但也并不好打,T3赛后因数据水安排重测,重测后还往上涨了\(2\)名,因为我的解法就是本着\(60pts\)部分分去的,没有卡掉我。T1花间叔祖原题。考虑另\(P=2\)则\(an......
  • 谷歌微软用电量比100多个国家还多!AI还将推高它们的耗电量
    最新统计显示,2023年谷歌、微软各自消费电力25TWh(250亿千瓦时)。在全球共197个国家中,谷歌微软各自消耗的电量比其中的100多个国家还要多。一家全球化互联网科技企业每年到底会消耗多少电力?数字可能会让你震惊。最新统计显示,2023年谷歌、微软各自消费电力25TWh(250亿千瓦时)。在......
  • C++ 插入排序
    【预告】        这几次将讲讲排序(从简单开始),废话不多说,直接切入正题【关于插入排序】【定义】    定义:插入排序是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入【时间复杂度】 ......
  • 林史·语其九(91-100)
    #91沟槽的中文输入法#92DZ:zyz呢DZ:他*的他过来把脸贴着门敲我们宿舍门玻璃,我说这头发怎么这么长,看着有点像zyzDZ:结果真他*是#93#94CTH:给我讲一个表面温馨但是实际上很恐怖的故事Qinyun:明天没有模拟赛#95HDK:我草,完了lbtl:咋HDK:我蚊帐里有蚊子Qinyu......
  • 我可以写代码写到退休吗?记录我的10年前端技术之旅
    今天是2024年4月26日,是我的32岁生日,也是我从事前端开发十年的日子,这篇文章是对我职业生涯的一次回顾,这次回顾颇有感慨,不仅回顾了之前工作的公司、同事,也看了一遍之前写的代码、写的文章,还有以前看的技术书的笔记。本文就以技术栈为线,把这十年的前端经历串起来,一来让读者一窥这十......
  • Wordpress安装到win10(2024年7月)
    目录1.wordpress介绍2下载应用2.1.wordpress2.2XAMPP 2.3PHPmyadmin3.配置应用3.1XAMPP进程3.2文件配置3.3phpmyadmin配置4.配置网页4.1数据库创建 4.2安装wordpress5.进入面板6.总结1.wordpress介绍WordPress是一个开源内容管理系统(CMS),它允许用户构......
  • 我可以写代码写到退休吗?记录我的10年前端技术之旅
    今天是2024年4月26日,是我的32岁生日,也是我从事前端开发十年的日子,这篇文章是对我职业生涯的一次回顾,这次回顾颇有感慨,不仅回顾了之前工作的公司、同事,也看了一遍之前写的代码、写的文章,还有以前看的技术书的笔记。本文就以技术栈为线,把这十年的前端经历串起来,一来让读者一......
  • 上市公司-企业数据要素利用水平(2010-2022年)
    企业数据要素利用水平数据:衡量数字化时代企业竞争力的关键指标在数字化时代,企业对数据的收集、处理、分析和应用能力成为衡量其竞争力和创新能力的重要标准。企业数据要素利用水平的高低直接影响其市场表现和发展潜力。企业数据要素利用水平的测算方法本数据集参考了史青春(2......