CSP-J/S 复赛算法 背包DP

文章目录

  • 前言
  • 背包DP的简介
    • 问题描述
    • 目标
    • 解决方法
    • 1. **定义状态**
    • 2. **状态转移方程**
    • 3. **初始化**
    • 4. **目标**
    • 举个例子
    • 动态规划解决背包问题的核心
  • DP背包问题示例代码
      • 问题描述
      • 代码实现
      • 核心代码讲解:
      • 举例:
      • 总结:
  • 总结


前言

背包问题是算法竞赛中的经典题型之一,特别是在CSP-J/S(中国信息学奥林匹克竞赛)复赛中,动态规划(DP)解决背包问题是一个常见且基础的重要内容。背包DP问题通过构建状态转移方程,利用「无后效性」这一特性,可以高效地解决一系列组合优化问题。本文将简要介绍如何在背包问题中运用动态规划思想,通过对状态的设计与转移公式的推导,最终求解出最优解。这种方法不仅是算法竞赛中的常见考点,也是在实际应用中有广泛运用的技巧。


背包DP的简介

背包问题(Knapsack Problem)是动态规划(DP)中的经典问题之一,它描述了一个选择物品的最优化问题。背包问题有很多变种,其中最常见的是0-1背包问题。我们以这个为例介绍一下。

问题描述

假设你有一个容量为 (C) 的背包,以及 (n) 件物品。每件物品都有两个属性:

  1. 重量 (w_i):物品的重量。
  2. 价值 (v_i):物品的价值。

你需要从这 (n) 件物品中选择若干件装入背包,但不能超过背包的容量 (C)。同时,你希望背包中的物品总价值最大化。每件物品只能被选一次(即「0-1」背包的「0-1」指的是每个物品只能取或者不取,不能分割)。

目标

最大化装入背包的物品的总价值,条件是物品的总重量不超过背包容量。

解决方法

动态规划(DP)可以很好地解决这个问题。我们一步步设计DP的步骤:

1. 定义状态

用 (dp[i][j]) 表示前 (i) 件物品在容量为 (j) 的背包里能够获得的最大价值。

  • 例如,(dp[3][5]) 表示用前三件物品在容量为5的背包里能获得的最大价值。

2. 状态转移方程

对第 (i) 件物品,我们有两种选择:

  • 不选择这件物品:那么最大价值就是前 (i-1) 件物品在容量 (j) 下的最大价值,表达式为:
    d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j] = dp[i-1][j] dp[i][j]=dp[i1][j]
  • 选择这件物品:如果当前物品 (i) 的重量 (w_i \leq j),那么我们可以选择它,最大价值就是当前物品价值 (v_i) 加上剩下的背包容量 (j - w_i) 时前 (i-1) 件物品的最大价值,表达式为:
    d p [ i ] [ j ] = d p [ i − 1 ] [ j − w i ] + v i dp[i][j] = dp[i-1][j-w_i] + v_i dp[i][j]=dp[i1][jwi]+vi

因此,综合这两种情况,状态转移方程为:
d p [ i ] [ j ] = max ⁡ ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − w i ] + v i ) dp[i][j] = \max(dp[i-1][j], dp[i-1][j-w_i] + v_i) dp[i][j]=max(dp[i1][j],dp[i1][jwi]+vi)

3. 初始化

对于初始状态,若不选任何物品或背包容量为 0,那么最大价值都是 0,因此:
d p [ 0 ] [ j ] = 0 (对于所有的  j ) dp[0][j] = 0 \quad \text{(对于所有的 \(j\))} dp[0][j]=0(对于所有的 j)
d p [ i ] [ 0 ] = 0 (对于所有的  i ) dp[i][0] = 0 \quad \text{(对于所有的 \(i\))} dp[i][0]=0(对于所有的 i)

4. 目标

最终,我们要的解就是 (dp[n][C]),即前 (n) 件物品在背包容量为 (C) 的情况下可以获得的最大价值。

举个例子

假设有 4 件物品,它们的重量和价值如下:

  • 物品 1:重量 2,价值 3
  • 物品 2:重量 3,价值 4
  • 物品 3:重量 4,价值 5
  • 物品 4:重量 5,价值 8

背包容量为 8。求解能够装入背包的最大价值是多少?

通过 DP 表的推算,最终可以得出最大价值为 11(选择物品 2 和物品 4,总重量为 3 + 5 = 8,总价值为 4 + 8 = 11)。

动态规划解决背包问题的核心

  • 无后效性:当前的状态(选择第几件物品,剩余容量多少)只与之前的状态相关,而不受未来的决策影响。
  • 子问题重叠:每一个子问题的解会被多次使用,因此通过 DP 的方式,可以避免重复计算,提高效率。

这种方法非常适合解决背包问题及其他类似的最优化问题。

DP背包问题示例代码

以下是一个用动态规划(DP)解决 0-1背包问题 的 C 语言代码示例,并附上核心代码的讲解。

问题描述

我们有 n 个物品,每个物品有重量 w[i] 和价值 v[i]。背包的容量为 C,我们需要选择物品,使得在不超过背包容量的情况下,物品的总价值最大化。

代码实现

#include <stdio.h>#define MAX_N 100  // 物品最大数量
#define MAX_W 1000 // 背包最大容量int dp[MAX_N + 1][MAX_W + 1]; // DP表,保存最大价值int max(int a, int b) {return (a > b) ? a : b;
}int knapsack(int n, int W, int w[], int v[]) {// 初始化DP表,0件物品或容量为0时价值都为0for (int i = 0; i <= n; i++) {for (int j = 0; j <= W; j++) {dp[i][j] = 0;}}// 动态规划,计算最大价值for (int i = 1; i <= n; i++) {for (int j = 0; j <= W; j++) {if (w[i-1] <= j) {// 状态转移方程:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1]] + v[i-1])dp[i][j] = max(dp[i-1][j], dp[i-1][j - w[i-1]] + v[i-1]);} else {// 如果当前物品重量大于容量,不能选该物品dp[i][j] = dp[i-1][j];}}}// 返回最大价值return dp[n][W];
}int main() {int n = 4; // 物品数量int W = 8; // 背包容量int w[] = {2, 3, 4, 5}; // 每个物品的重量int v[] = {3, 4, 5, 8}; // 每个物品的价值// 调用背包算法int max_value = knapsack(n, W, w, v);printf("最大价值: %d\n", max_value);return 0;
}

核心代码讲解:

  1. dp数组的定义:

    int dp[MAX_N + 1][MAX_W + 1];
    

    这里的 dp[i][j] 表示前 i 件物品在背包容量为 j 的时候可以获得的最大价值。dp 的维度是 (n+1) x (W+1),其中 n 是物品数量,W 是背包容量。

  2. 初始化DP表:

    for (int i = 0; i <= n; i++) {for (int j = 0; j <= W; j++) {dp[i][j] = 0;}
    }
    

    初始状态是没有物品(即 i = 0)或者背包容量为 0 时(即 j = 0),那么背包中的最大价值显然是 0。这个初始化确保了后续状态转移时有合理的初始值。

  3. 状态转移方程:

    dp[i][j] = max(dp[i-1][j], dp[i-1][j - w[i-1]] + v[i-1]);
    

    这是动态规划的核心部分,对于每个物品,我们有两种选择:

    • 不选第 i 件物品:此时最大价值和之前一样,即 dp[i-1][j]
    • 选第 i 件物品:此时需要确保物品重量小于等于背包容量(即 w[i-1] <= j),那么最大价值就是当前物品的价值 v[i-1] 加上背包剩余容量 j - w[i-1] 的最大价值 dp[i-1][j - w[i-1]]
  4. 返回结果:

    return dp[n][W];
    

    最终我们需要的答案是 dp[n][W],即前 n 件物品在背包容量为 W 时能够获得的最大价值。

举例:

对于输入:

  • 物品数量:4
  • 背包容量:8
  • 物品重量:{2, 3, 4, 5}
  • 物品价值:{3, 4, 5, 8}

程序输出:

最大价值: 11

这个结果对应于选择了物品 2 和物品 4,总重量为 3 + 5 = 8,总价值为 4 + 8 = 11。

总结:

这个代码通过动态规划解决 0-1 背包问题的核心在于状态转移方程,它通过子问题的解来推导出全局问题的最优解。每个子问题的解被存储在 dp 数组中,从而避免重复计算,极大地提高了效率。


总结

背包DP算法通过构建一个DP表格,依次推算每个子问题的最优解,最终得出整个问题的最优解。核心在于合理设计状态和状态转移方程,使得每一步的选择都依赖于之前的子问题结果。在CSP-J/S复赛中,背包问题的灵活变化考验选手对动态规划思想的掌握,理解其原理后能够有效提升问题解决的效率。熟练掌握背包问题的动态规划方法,不仅能够应对竞赛中的挑战,更能为更复杂的优化问题打下坚实基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/55646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件测试:postman详解

一、Postman背景介绍 用户在开发或者调试网络程序或者是网页B/S模式的程序的时候是需要一些方法来跟踪网页请求的&#xff0c;用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具。今天给大家介绍的这款网页调试工具不仅可以调试简单的css、html、脚本等简单的网…

自然语言处理(NLP):用Python进行情感分析的深入探索

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 前言 随着互联网的发展,社交媒体、产品评价和新闻评论等各种文本数据的涌现,情感分析作为自然语言处理(NLP)领域的一项重要技术,逐渐成为研究和商业应用中的热点之一。情感分析的目标是通过分析文本中的情感…

ubuntu增加swap

ubuntu增加swap 创建myswapfile上电启动 创建myswapfile 首先在你的目录中创建一个myswapfile并创建myswapfile文件&#xff0c;这个名字可以改成你自己的 mkdir myswapfile cd myswapfile/ # 单个为1G&#xff0c;数量为7&#xff0c;总共7g内存 dd if/dev/zero ofswapfile …

更新C语言题目

1.以下程序输出结果是() int main() {int a 1, b 2, c 2, t;while (a < b < c) {t a;a b;b t;c--;}printf("%d %d %d", a, b, c); } 解析:a1 b2 c2 a<b 成立 ,等于一个真值1 1<2 执行循环体 t被赋值为1 a被赋值2 b赋值1 c-- c变成1 a<b 不成立…

【AI大模型-文心-思维树解读-仓颉精通之路-10】

提问&#xff1a;如果是学习一门计算机语言&#xff0c;基于哪种prompt的框架&#xff0c;会得到更好的帮助 回答&#xff1a;如下 版本&#xff1a;文心大模型3.5 在学习一门计算机语言时&#xff0c;为了获得更好的帮助&#xff0c;可以基于以下几种prompt的框架来构建你的学…

如何搭建自己的域名邮箱服务器?Poste.io邮箱服务器搭建教程,Linux+Docker搭建邮件服务器的教程

Linux系统Docker搭建Poste.io电子邮件服务器&#xff0c;搭建属于自己的域名邮箱服务器&#xff0c;可以无限收发电子邮件&#xff08;Email&#xff09;&#xff01; 视频教程&#xff1a;https://www.bilibili.com/video/BV11p1mYaEpM/ 前言 什么是域名邮箱&#xff1f; …

各省份-产业链现代化水平(2001-2022年)

产业链现代化水平是一个综合性指标&#xff0c;它为我们提供了一个多维度的视角来评估各省份在产业链现代化进程中的发展水平。这个指标涵盖了技术创新、产业升级、生产效率、产业结构优化等多个方面&#xff0c;包含原始数据、测算结果以及参考文献。 2001年-2022年各省份-产…

矩阵学习过程中的一些思考

2024.09.27&#xff08;学习鸢尾花书_矩阵力量_Ch20&#xff09; &#xff08;1&#xff09;所有中心过原点的椭圆都可以用一个二维矩阵表示&#xff0c;且特征值表示长短轴长度&#xff0c;特征向量表示长短轴所在方向的单位向量&#xff08;表征椭圆旋转方向&#xff09;&am…

C语言入门基础题(力扣):完成旅途的最少时间(C语言版)

1.题目&#xff1a; 给你一个数组 time &#xff0c;其中 time[i] 表示第 i 辆公交车完成 一趟旅途 所需要花费的时间。 每辆公交车可以 连续 完成多趟旅途&#xff0c;也就是说&#xff0c;一辆公交车当前旅途完成后&#xff0c;可以 立马开始 下一趟旅途。每辆公交车 独立 …

论文翻译 | Generated Knowledge Prompting for Commonsense Reasoning

摘要 整合外部知识是否有利于常识推理&#xff0c;同时保持预训练序列模型的灵活性&#xff0c;这仍然是一个悬而未决的问题。为了研究这个问题&#xff0c;我们开发了生成知识提示&#xff0c;它包括从语言模型生成知识&#xff0c;然后在回答问题时提供知识作为附加输入。我们…

spring揭秘25-springmvc05-过滤器与拦截器区别(补充)

文章目录 【README】【1】springmvc拦截器回顾【1.1】定义与应用【1.2】拦截器作用范围 【2】servlet过滤器回顾【2.1】过滤器定义与应用【2.2】过滤器作用范围 【3】springmvc拦截器与servlet过滤器区别&#xff08;重要*&#xff09;【3.1】拦截方法调用代码实现 【README】 …

【Java】IntelliJ IDEA开发环境安装

一、下载 官方地址&#xff1a;https://www.jetbrains.com/idea/ 点击Download直接下载 二、安装 双击安装包&#xff0c;点击Next 选择安装路径&#xff0c;点击Next 勾选安装内容 安装完成。 三、创建项目 打开IDEA&#xff0c;填写项目名称&#xff0c;选择项目安装路径…

elasticsearch单个node节点写入数据

不设置用户名及密码的情况下,直接写入 我以为没有明确的设置就没有账号密码了,发现还是不行,竟然是非root的用户名,当初./bin/elasticsearch时创建的非sudo用户,elasticsearch 用户名(不是python虚拟环境的用户名),密码另外设置了,此时也是elasticsearch的密码,现在…

如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue

TOC ssm779基于SSM的宠物服务平台的设计与实现vue 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#x…

安全帽头盔检测数据集 3类 12000张 安全帽数据集 voc yolo

安全帽头盔检测数据集 3类 12000张 安全帽数据集 voc yolo 安全帽头盔检测数据集介绍 数据集名称 安全帽头盔检测数据集 (Safety Helmet and Person Detection Dataset) 数据集概述 该数据集专为训练和评估基于YOLO系列目标检测模型&#xff08;包括YOLOv5、YOLOv6、YOLOv7…

【C++ STL】手撕vector,深入理解vector的底层

vector的模拟实现 前言一.默认成员函数1.1常用的构造函数1.1.1默认构造函数1.1.2 n个 val值的构造函数1.1.3 迭代器区间构造1.1.4 initializer_list 的构造 1.2析构函数1.3拷贝构造函数1.4赋值运算符重载 二.元素的插入,删除,查找操作2.1 operator[]重载函数2.2 push_back函数:…

OpenCV视频I/O(11)视频采集类VideoCapture之设置视频捕获设备的属性函数 set()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 VideoCapture 中设置一个属性。 在OpenCV中&#xff0c;cv::VideoCapture::set() 函数用于设置视频捕获设备的属性。这些属性可以包括分辨率、…

Redis篇(面试题 - 连环16炮)(持续更新迭代)

目录 目录 目录 &#xff08;第一炮&#xff09;一、Redis&#xff1f;常用数据结构&#xff1f; 1. 项目里面到了Redis&#xff0c;为什么选用Redis&#xff1f; 2. Redis 是什么&#xff1f; 3. Redis和关系型数据库的本质区别有哪些&#xff1f; 4. Redis 的线程模型…

4 思科模拟器的介绍和使用

4 思科模拟器的介绍和使用 思科的IOS给我们提供了三大模式 设备开机后&#xff0c;进入的模式是【用户模式】 Router表示设备的名称 “>”表示用户模式 在用户模式输入"?" 可列出在用户模式可以使用的命令 第二种模式是特权模式,输入enable进入特权模式&…

【C++】入门基础介绍(上)C++的发展历史与命名空间

文章目录 1. 前言2. C发展历史2. 1 C版本更新特性一览2. 2 关于C23的一个小故事: 3. C的重要性3. 1 编程语言排行榜3. 2 C在工作领域中的应用 4. C学习建议和书籍推荐4. 1 C学习难度4. 2 学习书籍推荐 5. C的第一个程序6. 命名空间6. 1 namespace的价值6. 2 namespace的定义6. …