动态规划(背包问题)--是否逆序使用的问题--二进制拆分的问题

news2025/2/26 13:27:24

动态规划(背包问题)

  • 题目链接
    • 01背包
      • 代码
    • 完全背包问题
      • 代码
    • 多重背包问题 I
      • 代码
  • 什么时候适用逆序
    • 多重背包问题 II(超百万级的复杂度)
      • 代码
  • 关于二进制拆分

题目链接

01背包

在这里插入图片描述

代码

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <queue>

#include <cctype>
using namespace std;
int n, V;
int v[1010], w[1010], dp[1010];
int main() {
	cin >> n >> V;
	for (int i = 0; i < n; i++)
		cin >> v[i] >> w[i];
	for (int i = 0; i < n; i++) {
		for (int j = V; j >= v[i]; j--) {
			dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
		}
	}
	cout << dp[V] << endl;
	return 0;
}

完全背包问题

在这里插入图片描述

代码

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <queue>

#include <cctype>
using namespace std;
int n, V;
int v[1010], w[1010], dp[1010];
int main() {
	cin >> n >> V;
	for (int i = 0; i < n; i++)
		cin >> v[i] >> w[i];
	for (int i = 0; i < n; i++) {
	//01背包这是逆序,以保证刚被放入的不会被放入第二次
	//完全背包没次数限制,只要保证局部最优解(像贪心)
		for (int j = v[i]; j <= V; j++) {
			dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
		}
	}
	cout << dp[V] << endl;
	return 0;
}

多重背包问题 I

在这里插入图片描述

代码

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <queue>

#include <cctype>
using namespace std;
int n, V;
int v[1010], w[1010], s[1010], dp[1010];
int main() {
	cin >> n >> V;
	for (int i = 0; i < n; i++)
		cin >> v[i] >> w[i] >> s[i];
	for (int i = 0; i < n; i++) {
	//注意未放置重复使用,这里用的逆序
		for (int j = V; j >= 0; j--) {
			for (int k = 0; k <= s[i]; k++)
				if (j - v[i]*k >= 0)
					dp[j] = max(dp[j], dp[j - v[i] * k] + w[i] * k);
		}
	}
	cout << dp[V] << endl;
	return 0;
}

什么时候适用逆序

如果你的dp数组用的二维的话,就能确保状态更新时使用的是上一轮(即前一种物品)的值。

但是! 可见我的代码dp数组全是用的一维数组,这个时候就有是否逆序的烦恼了呀!

那什么时候用逆序呢?

哎!先上总结:在这里插入图片描述
原因如下:

首先,为什么要逆序遍历?防止重复选取:逆序保证在更新 dp[j] 时,dp[j - v[i]] 尚未被修改,即防止是上一轮的值被再次使用,哎~这就要有人问了,动态规划不就是递推的吗?不就是要用前几轮被更新的值吗?你想奥如果此时i=1,即仍然处于更新第一个物品的情况中,但是01背包中每个物品就一次,如果正序遍历,在内存允许的情况下,物品1又会被放一次。

但是什么情况下就无所谓呢?没错就是物品数量无限的时候,即完全背包问题。它没有数量限制,如果此时用逆序,就会导致在容量为V的时候只放了一共物品一,顺序的话就可以放V/v个物品一了。

那么多重背包为什么也要用逆序呢?多重背包多了一个参数——物品各自的数量,所以在双重循环中又加了一层,即数量的遍历,目的是遍历在数量允许的前提下时,容量允许的价值数量。
讲的比较抽象,轻喷:)

(虽然这个博客也没啥真人看(除了我自己)

多重背包问题 II(超百万级的复杂度)

百万级以内的复杂度,上述代码都能解决

在这里插入图片描述

代码

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <queue>

#include <cctype>
using namespace std;
//为什么是2w5?因为2000会被拆成11项,若2000个物品则一共就是2w2项
const int N = 25000;
int n, m, v[N], w[N], dp[N];
int main() {
	cin >> n >> m;
	int cnt = 0;
//实施二进制拆分
	for (int i = 1; i <= n; i++) {
		int a, b, s;
		cin >> a >> b >> s;
		int k = 1;
		while (k <= s) {
			cnt++;
			v[cnt] = a * k;
			w[cnt] = b * k;
			s -= k;
			k *= 2;
		}
		if (s > 0) {
			cnt++;
			v[cnt] = a * s;
			w[cnt] = b * s;
		}
	}
	for (int i = 1; i <= cnt; i++) {
		for (int j = m; j >= v[i]; j--) {
			dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
		}
	}
	cout << dp[m] << endl;
	return 0;
}

关于二进制拆分

这就有人要问了,和多重背包问题 I一模一样的题,还是一样的代码提交一遍不就好了嘛,水题!^ ^

对于多重背包问题 II,不一样的地方就是数据范围变大了,又是三重循环可想而知复杂度早就飙到不知道哪去了。

那么怎么解答呢?哎这就有大佬想到了,这个数字组合问题嘛,我们拆分就好了,怎么拆呢?哎~二进制拆分!!!(woc不知道谁想出来的,我第一次看震惊到我了,这么聪明的思路)

什么是二进制拆分呢?

假设你有7枚硬币,面值都是1元。现在想用这些硬币凑出0~7元中的任意金额。常规做法是带7枚硬币。
二进制拆分思路:
带1元、2元、4元的三枚硬币。你会发现这三枚硬币可以组合出0~7元的所有金额!!!(woc了nb)

这就是二进制拆分的核心思想:用最少的“虚拟物品”覆盖所有可能的数量组合。

处理次数对比一下
在这里插入图片描述

拆分完之后,再转换为01背包问题

哎~这么牛逼的算法想知道还能用在哪些地方吗?

哎!我就是这么的周到!

1、普通数据。例如:物品的件数、次数、文件大小(1000MB,拆分为 512MB, 256MB, 128MB, 64MB, 32MB, 8MB。)

2、快速幂算法:计算a^13 =a^1+ a^4+ a^8(对应1101) ,减少乘法次数

3、场景划分为不同大小的块(如 8x8, 16x16 像素)

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

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

相关文章

Mac 版 本地部署deepseek ➕ RAGflow 知识库搭建流程分享(附问题解决方法)

安装&#xff1a; 1、首先按照此视频的流程一步一步进行安装&#xff1a;(macos版&#xff09;ragflowdeepseek 私域知识库搭建流程分享_哔哩哔哩_bilibili 2、RAGflow 官网文档指南&#xff1a;https://ragflow.io 3、RAGflow 下载地址&#xff1a;https://github.com/infi…

姿态矩阵/旋转矩阵/反对称阵

物理意义&#xff0c;端点矢量角速率叉乘本身向量&#xff1b; 负号是动系b看固定系i是相反的&#xff1b; 一个固定 在惯性导航解算中&#xff0c;旋转矢量的叉乘用于描述姿态矩阵的微分方程。你提到的公式中&#xff0c; ω i b b \boldsymbol{\omega}_{ib}^b \times ωibb…

【大语言模型】【整合版】DeepSeek 模型提示词学习笔记(散装的可以看我之前的学习笔记,这里只是归纳与总结了一下思路,内容和之前发的差不多)

以下是个人笔记的正文内容: 原文在FlowUs知识库上&#xff0c;如下截图。里面内容和这里一样&#xff0c;知识排版好看一点 一、什么是 DeepSeek 1. DeepSeek 简介 DeepSeek 是一家专注于通用人工智能&#xff08;AGI&#xff09;的中国科技公司&#xff0c;主攻大模型研发与…

ollama无法通过IP:11434访问

目录 1.介绍 2.直接在ollama的当前命令窗口中修改&#xff08;法1&#xff09; 3.更改ollama配置文件&#xff08;法2&#xff09; 3.1更新配置 3.2重启服务 1.介绍 ollama下载后默认情况下都是直接在本地的11434端口中运行&#xff0c;绑定到127.0.0.1(localhost)&#x…

Bugku CTF CRYPTO

Bugku CTF CRYPTO 文章目录 Bugku CTF CRYPTO聪明的小羊ok[-<>]散乱的密文.!? 聪明的小羊 描 述: 一只小羊翻过了2个栅栏 fa{fe13f590lg6d46d0d0} 分 析&#xff1a;栅栏密码&#xff0c;分2栏&#xff0c;一个栏里有11个 ①手动解密 f a { f e 1 3 f 5 9 0 l g 6 d 4 …

【洛谷】【ARC100E】Or Plus Max(高维前缀和)

传送门&#xff1a;Or Plus Max 高维前缀和 题目描述 長さ 2N の整数列 A0​, A1​, ..., A2N−1​ があります。&#xff08;添字が 0 から始まることに注意&#xff09; 1 ≤ K ≤ 2N−1 を満たすすべての整数 K について、次の問題を解いてください。 i,j を整数と…

SmolLM2:多阶段训练策略优化和高质量数据集,小型语言模型同样可以实现卓越的性能表现

SmolLM2 采用创新的四阶段训练策略&#xff0c;在仅使用 1.7B 参数的情况下&#xff0c;成功挑战了大型语言模型的性能边界&#xff1a; 在 MMLU-Pro 等测试中超越 Qwen2.5-1.5B 近 6 个百分点数学推理能力&#xff08;GSM8K、MATH&#xff09;优于 Llama3.2-1B在代码生成和文…

《Effective Objective-C》阅读笔记(中)

目录 接口与API设计 用前缀避免命名空间冲突 提供“全能初始化方法” 实现description方法 尽量使用不可变对象 使用清晰而协调的命名方式 方法命名 ​编辑类与协议命名 为私有方法名加前缀 理解OC错误模型 理解NSCopying协议 协议与分类 通过委托与数据源协议进行…

Hbase客户端API——语句大全

目录 创建表&#xff1a; 插入数据&#xff1a; 删除数据&#xff1a; 修改数据&#xff1a; 查询数据&#xff1a;Get 查询数据&#xff1a;Scan 查询数据&#xff1a;过滤查询 创建表&#xff1a; 检验&#xff1a; 插入数据&#xff1a; 验证 一次多条数据插入 验证&…

MQ(Message Queue)

目录 MQ(Message Queue)基本概念 为什么要使用消息队列&#xff1f; 使用消息队列有什么缺点&#xff1f; 如何保证消息不丢失?(如何保证消息的可靠性传输?/如何处理消息丢失的问题?) 通用的MQ场景&#xff1a; RabbitMQ如何保证消息不丢失&#xff1f; 生产者丢数据…

计算机网络————(三)

前文二 前文一 Websocket协议 是一种存在TCP协议之上的协议 当客户端需要了解服务器是否更新就需要不断给客户端发送请求询问是否更新&#xff0c;这行会造成服务端压力很大 而Websocket相当于服务器一旦更新了就会给客户端发送消息表明自己更新了&#xff0c;类似客户端订阅…

【音视频】音视频录制、播放原理

一、音视频录制原理 通常&#xff0c;音视频录制的步骤如下图所示&#xff1a; 我们分别从音频和视频开始采样&#xff0c;通过麦克风和摄像头来接受我们的音频信息和图像信息&#xff0c;这通常是同时进行的&#xff0c;不过&#xff0c;通常视频的采集会比音频的采集慢&…

deepseek 导出导入模型(docker)

前言 实现导出导入deepseek 模型。deepseek 安装docker下参考 docker 导出模型 实际生产环境建议使用docker-compose.yml进行布局&#xff0c;然后持久化ollama模型数据到本地参考 echo "start ollama" docker start ollama#压缩容器内文件夹&#xff0c;然后拷贝…

基于Redis 的分布式 session 图解

Redis 分布式 Session 工作原理 1. 传统 Session 的问题 在传统单服务器环境中&#xff0c;HTTP Session 存储在应用服务器的内存中。这在分布式系统中会导致问题&#xff1a; 用户的请求可能被分发到不同服务器&#xff0c;导致会话不一致服务器宕机会导致会话丢失需要依赖…

DeepSeek-R1本地部署保姆级教程

一、DeepSeek-R1本地部署配置要求 &#xff08;一&#xff09;轻量级模型 ▌DeepSeek-R1-1.5B 内存容量&#xff1a;≥8GB 显卡需求&#xff1a;支持CPU推理&#xff08;无需独立GPU&#xff09; 适用场景&#xff1a;本地环境验证测试/Ollama集成调试 &#xff08;二&a…

【deepseek】本地部署+webui访问

背景 最近deepseek很火&#xff0c;但是官网的老是被限流使用&#xff0c;还有就是自己也想着玩一玩&#xff0c;于是准备在自己电脑跑一个 直接附上结果地址mydeepseek 准备工作 windows和linux都可 我这里选择linux&#xff0c;ubuntu系统 安装ollama 看下图&#xff0…

博客系统笔记总结 2( Linux 相关)

Linux 基本使用和程序部署 基本命令 文件操作 显示当前目录下的文件 ls&#xff1a;显示当前目录下的文件 ll&#xff1a;以列表的形式展示&#xff0c;包括隐藏文件 进入目录 && 显示当前路径 cd&#xff1a;进入目录&#xff08;后面跟相对路径或者绝对路径&…

Flutter - 基础Widget

Flutter 中万物皆 Widget&#xff0c;基础Widget 同步对应 Android View. 普通文本 Text /*** 控制文本样式统一使用 style:TextStyle, 例&#xff1a;fontSize(字体大小),color(颜色),shadows(阴影)等等* 控制文本布局需单独设置&#xff1a;* textAlign(文不对齐方式)* te…

如何在 Linux 上安装和配置 Zsh

文章目录 如何在 Linux 上安装和配置 Zsh1. 安装 Zsh1.1 在 Ubuntu/Debian 上安装1.2 在 CentOS/RHEL/Fedora 上安装1.3 在 Arch Linux 上安装1.4 验证 Zsh 安装 2. 设置 Zsh 为默认 Shell2.1 验证默认 shell 3. 配置 Zsh3.1 使用 Oh My Zsh3.1.1 安装 Oh My Zsh3.1.2 启用插件…

【System Verilog and UVM基础入门26】Verdi使用教程指南

《Verdi使用教程指南 》 下载链接&#xff1a; https://download.csdn.net/download/TommiWei/90429701https://download.csdn.net/download/TommiWei/90429701 朋友你好&#xff0c;不管你是否使用过Verdi这款EDA仿真工具。 不管你是否还在寻找免费的使用教材。 不管你是否…