完全背包问题

01背包问题和完全背包问题 01背包 01背包字面意思来看0就是不拿,1就是拿,且每次只能拿一个物品放入背包。 开二维数组的状态方程: 此情景为往固定容量的背包里装物品,使包内物品为最大价值 实际上就是在每个物品的基础上,遍历所有可能的背包空间,如果放得下去就比较放与不放对价值的影响 一维数组的状态方程: ... 阅读详情

完全背包问题的特点是每种物品数量没有限制,可以无限使用。很容易定义完全背包状态转移方程,根据第i件物品进行划分进行决策。设第i个物品选择k个,于是:

            W[i,j]=max{ W[i -1,j - k*v[ i ] ]+k*p[i] }   (0<= k<=j / v[i] ),k=0时即表示不用选择的情况。此时对于每一个状态i,我们要考虑(1+2+..V)/v[i]次。当v[i]比较小时,光考虑第i个状态时间复杂度就接近O(V^2),总时间复杂度接近O(NV^2).当然还可以对其做一些改进。为了方便操作,将价格和体积捆绑为一个结构体Goods,两个属性是p和v。状态转移方程可以写为:

            W[i,j]=max{ W[i -1,j - k*goods[i].v+k*goods[i].p }   (0<= k<=j / v[i] ) .

      对于不要求背包装满的情况,首先可以做一些简单的优化,对于第i个物品和第j个物品,若满足 v[i]<=v[j]且p[i]>=p[j]时,我们完全可以不考虑第j个物品,这是由于物品i相对于物品j来说是物美价廉。我们可以用桶排序方法来完成优化。建立bucket[1...V],超过体积V的物品直接删除。当没有体积为 i 的物品时,bucket[i]设置为空。当有多个体积为i的物品时,bucket[i]中放体积为i但是价格最大的那个物品。然后扫描一次桶,若i<j但是bucket[i].p>=bucket[j].p则将bucket[j]设置为空(删掉)。总的过程时间为o(V).,空间也为O(V).但是对于要求将背包装满的情况则不能这样优化,否则本来有解也可能导致无解。当然这些优化并不能改变最坏情况下的复杂度。下面一种思想将完全背包问题转变为01背包问题,对于第 i 个物品,最多有k=V/v[i]个.从而我们可以将第i个物品分解为k个一样的物品。这样问题就转化为了01背包问题,然而时间复杂度没变。另一个改进是采用二进制的思想:将第i个物品质分解为体积:v[i] , 2*v[i],v[i]*2^2...v[i]*2^log(V/v[i]),相应价值也类似递增,这是由于二进制可以表示任意数。这样得到了一个不错的优化结果,第i个物品分解为log(V/v[i])+1个,第 i 个状态转移次数大约为(log(V/v[i])+1)*V,当v[i]比较小时,此式子接近O(VlogV),于是总的时间度接近O(NVlogV),已经得到了一个很大的改进。以下代码是不要背包求装满的情况,开始部分利用桶排序原则删除了一些物品,然后将物品分解转变为二进制。

<span style="font-size:10px;">/*不要求背包装满*/</span>
<span style="font-size:10px;">#include<iostream>
using namespace std;
#define MAX_SIZE 500
int N, V;
struct Goods{
	int p, v;
};
Goods goods[MAX_SIZE];
Goods bucket[MAX_SIZE];
bool flag[MAX_SIZE];
int W[MAX_SIZE];
int main(){
	int i, j,pos,nowPrice,ans,total;
	Goods temp;
	memset(flag, 0, sizeof(flag));
	cin >> N >> V;
	for (i = 1; i <=N; i++)
		cin >> goods[i].v >> goods[i].p;
	//-------------------------------------------------------------------------
	for (i = 1; i <=N; i++){
		if (goods[i].v>V)
			continue;
		else  if (!flag[goods[i].v] || goods[i].p>bucket[goods[i].v].p){
			flag[goods[i].v] = 1;
			bucket[goods[i].v] = goods[i];
		}
	}
	pos =1,ans=1;
	while (!flag[pos])
		pos++;
	nowPrice = bucket[pos].p;
	goods[ans++] = bucket[pos];
	for (i = pos + 1; i <=V; i++){
		if (flag[i] && nowPrice < bucket[i].p){
			nowPrice = bucket[i].p;
			goods[ans++] = bucket[i];
		}
	}

	/*--------------------------------------------------------------以上是优化过程代码*/
	pos = ans;
	for (i = 1; i < ans; i++){
		temp = goods[i];</span>
<span style="font-size:10px;">                total=temp.v;
		while(total<V){
			temp.v *= 2;
			temp.p *= 2;
			goods[pos++] = temp;</span>
<span style="font-size:10px;">                        total+=temp.v;
		}
	}
	/*--------------------------以上完成拆分,如今已有pos个物品,下面利用01背包解法*/
	memset(W, 0, sizeof(W));
	for (i = 1; i <= pos; i++){
		for (j = V; j >= goods[i].v; j--)
		if (W[j]< W[j - goods[i].v] + goods[i].p)
			W[j] = W[j - goods[i].v] + goods[i].p;
	}
	cout << W[V] << endl;
	return 0;
}</span>

在要求背包装满的情况下,就不得做删除的优化了。HDU1004就是一个要求背包装满的问题。下面是HDU1004:

Problem Description
Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. The main income for this action comes from Irreversibly Bound Money (IBM). The idea behind is simple. Whenever some ACM member has any small money, he takes all the coins and throws them into a piggy-bank. You know that this process is irreversible, the coins cannot be removed without breaking the pig. After a sufficiently long time, there should be enough cash in the piggy-bank to pay everything that needs to be paid. 

But there is a big problem with piggy-banks. It is not possible to determine how much money is inside. So we might break the pig into pieces only to find out that there is not enough money. Clearly, we want to avoid this unpleasant situation. The only possibility is to weigh the piggy-bank and try to guess how many coins are inside. Assume that we are able to determine the weight of the pig exactly and that we know the weights of all coins of a given currency. Then there is some minimum amount of money in the piggy-bank that we can guarantee. Your task is to find out this worst case and determine the minimum amount of cash inside the piggy-bank. We need your help. No more prematurely broken pigs! 
 

Input
The input consists of T test cases. The number of them (T) is given on the first line of the input file. Each test case begins with a line containing two integers E and F. They indicate the weight of an empty pig and of the pig filled with coins. Both weights are given in grams. No pig will weigh more than 10 kg, that means 1 <= E <= F <= 10000. On the second line of each test case, there is an integer number N (1 <= N <= 500) that gives the number of various coins used in the given currency. Following this are exactly N lines, each specifying one coin type. These lines contain two integers each, Pand W (1 <= P <= 50000, 1 <= W <=10000). P is the value of the coin in monetary units, W is it's weight in grams. 
 

Output
Print exactly one line of output for each test case. The line must contain the sentence "The minimum amount of money in the piggy-bank is X." where X is the minimum amount of money that can be achieved using coins with the given total weight. If the weight cannot be reached exactly, print a line "This is impossible.". 
 

Sample Input
3 10 110 2 1 1 30 50 10 110 2 1 1 50 30 1 6 2 10 3 20 4
 

Sample Output
The minimum amount of money in the piggy-bank is 60. The minimum amount of money in the piggy-bank is 100. This is impossible.
 
这是一个要求典型的要求背包装满的完全背包问题。直接给出二进制分解后的AC代码:
<span style="font-size:10px;">#include<iostream>
using namespace std;
#define MAX_SIZE 10002
int N, V;
struct Goods{
	int p, v;
};
Goods goods[MAX_SIZE];
int W[MAX_SIZE];
int main(){
	int i, j,pos,ans,E,F,T,total;
	Goods temp;
	cin >> T;
	while (T--){
		memset(W, -1, sizeof(W));
		W[0] = 0;
		cin >> E >> F;
		V = F - E;
		cin >> N;
		for (i = 1; i <= N; i++)
			cin >>goods[i].p>>goods[i].v;
		ans = N + 1;
		for (i = 1; i <=N; i++){
			temp = goods[i];
			total = temp.v;
			while (total <V){
				temp.v *= 2;
				temp.p *= 2;
				goods[ans++] = temp;
				total += temp.v;
			}
		}
		for (i = 1; i <ans; i++){
			for (j = V; j >= goods[i].v; j--){
				pos = j - goods[i].v;
				if (W[pos] != -1 && (W[j] == -1 || W[pos] + goods[i].p < W[j]))
					W[j] = W[pos] + goods[i].p;
			}
		}
		if (W[V] != -1)
			cout << "The minimum amount of money in the piggy-bank is " << W[V] << '.' << endl;
		else
			cout << "This is impossible." << endl;
	}
	return 0;
}</span>

二进制分解基于思想是将完全背包问题转化为01背包问题。但是这种方法也不是完全背包最快的办法,最后还有时间复杂度为O(NV)的算法。进一步改进,并让 j 枚举 0..V的情况,有O(VN)的算法。改进后状态转移方程为:
                    W[ j ]=MAX{W[ j ],W[ j-v[ i] ] +p[ i ]};
在01背包问题中,我们只关心第i中物品选还是不选。而完全背包是每件物品最多可选V/v[i]件。所以在考虑加选一种第i中物品时前面在子结果W[ i,j-v[i]]中可能已经选过第i件物品。即是要采用 for j=v[i] to V的循环,同样的求解HDU 1114 时,使用时间比二进制方法快很多:
<span style="font-size:10px;">#include<iostream>
using namespace std;
#define MAX_SIZE 10002
int N, V;
struct Goods{
	int p, v;
};
Goods goods[MAX_SIZE];
int W[MAX_SIZE];
int main(){
	int i, j,pos,E,F,T;
	cin >> T;
	while (T--){
		memset(W, -1, sizeof(W));
		W[0] = 0;
		cin >> E >> F;
		V = F - E;
		cin >> N;
		for (i = 1; i <= N; i++)
			cin >>goods[i].p>>goods[i].v;
		for (i = 1; i <=N; i++){
			for (j = goods[i].v; j <= V; j++){
				pos = j-goods[i].v;
				if (W[pos] != -1 && (W[j] == -1 || W[pos] + goods[i].p < W[j]))
					W[j] = W[pos] + goods[i].p;
			}
		}
		if (W[V] != -1)
			cout << "The minimum amount of money in the piggy-bank is " << W[V] << '.' << endl;
		else
			cout << "This is impossible." << endl;
	}
	return 0;
}</span>



Claude Code Auto Memory 的 Storage Location,SAP ABAP 项目里的本地记忆仓库应该怎么理解 本文介绍了 SAP ABAP 项目中 Claude Code 的 auto memory 机制,重点探讨了其存储位置的设计原理。auto memory 不是存储在项目目录中,而是默认位于 ~/.claude/projects/<project>/memory/,其中 <project> 基于 Git 仓库路径推导,确保同一仓库下的所有工作目录和分支共享记忆。记忆目录包含入口文件 MEMORY.md(仅加载前 200 行)和详细主题文件,这种分层设计类似 CDS View 架构思想。文章还分析了按 Git 仓 阅读详情

相关推荐

更换光猫的原理与方法

当你给装维打电话说你需要更换光猫时,对于装维来说,他并不需要知道怎么更换,他只需要生成一张工单,由后台进行业务操作后,在去用户家把新光猫给装好即可,此时装维到底起到了什么作用呢?我想可能只是运输员吧,把一个设备从一个地方运到另一个地方罢了,此时并不能指望装维做什么,因为本质上来说装维的能力真的很差很差,我是不知道那些装维哪来的勇气做视频,还说自己什么什么能力很强?很强吗?吹牛的技术确实很强。 更换光猫之前,需要先明白为什么要更换光猫,怎么更换光猫,更换后不能用怎么办?怎么才能更换成功,换光猫以后被限速了怎么

qq_34146290的博客 1万+

完全背包理论基础

因为dp[j] 是根据 下标j之前所对应的dp[j]计算出来的。只要保证下标j之前的dp[j]都是经过计算的就可以了。有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i]。我们知道01背包内嵌的循环是从大到小遍历,为了保证每个物品仅被添加一次。,求解将哪些物品装入背包里物品价值总和最大。

qq_63953838的博客 147

解决OpenCASCADE性能瓶颈:显示加速与三角剖分优化全攻略

本文深入探讨OpenCASCADE在工业设计和CAD建模中的性能优化策略,重点解决显示加速与三角剖分等核心瓶颈问题。通过智能刷新控制、显示数据结构优化和动态LOD技术,显著提升渲染效率和交互体验,适用于复杂场景下的三维可视化应用。

weixin_30752699的博客 344

【动态规划】背包问题 {01背包问题;完全背包问题;二维费用背包问题}

【动态规划】背包问题 {01背包问题;完全背包问题;二维费用背包问题}

52Herzt的博客 5527

IEEE Transactions on Industrial Informatics(TII)投稿全流程解析:从准备到成功提交

本文详细解析了向IEEE Transactions on Industrial Informatics(TII)投稿的全流程,涵盖从投稿前的格式准备、内容结构优化到在线提交系统实操等关键环节。重点强调了遵守TII严格的格式规范、双盲评审要求以及如何构建有说服力的学术叙述,旨在帮助研究者提升稿件质量,顺利通过评审。

weixin_28396629的博客 1864

【GameFramework框架内置模块】8、文件系统(File System)

最近好忙,鸽了好久。不能颓废了,继续发力。今天分享的是GF框架的文件系统。首先,引用比较官方的说法:GF的FileSystem虚拟文件系统,使用类似磁盘存储的感念对零散的文件进行集中管理,优化资源加载时产生的内存分配,也可以对资源进行局部片段加载,极大的提升了资源加载的性能。通俗点讲就是,我这个模块就是加载磁盘文件的,优化加载时产生的内存分配。那么,它是怎么优化的呢?

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 2452

【算法】一文带你搞懂完全背包!(附背包问题总结)

详解动态规划中的完全背包问题原理及应用,了解多重背包,以及总结笔试面试中解决背包问题的关键。

Conner7的博客 7444

基于STM32与FPGA的数据采集系统的设计与实现

数据采集系统在现代工程中起着至关重要的作用,用于实时获取和处理各种传感器或外部设备的数据。在本文中,我们将探讨如何基于STM32微控制器和FPGA(现场可编程门阵列)实现一个高效的数据采集系统。我们可以使用STM32的UART、SPI或I2C接口与各种传感器或外部设备进行通信,并通过GPIO口实现控制功能。在硬件连接完成后,我们可以通过STM32控制FPGA的配置和数据传输。STM32作为主控单元负责与外部设备进行通信和数据处理,而FPGA则用于高速数据采集和实时处理。具体的通信协议取决于连接的设备类型。

UbiSqlserver的博客 1797

完全背包问题(动态规划(DP))

原题 完全背包问题 有n种重量和价值分别为wi,vi的物品。从这些物品中挑选总重量不超过W的物品,求出挑选物品价值总和的最大值。在这里,每种物品可以挑选任意多件。 1 1 1 样例输入 n=3 (w,v)={(3,4),(4,5),(2,3)} W=7 样例输出 10(0号物品选1个,2号物品选2个) 涉及知识及算法 递推关

快速进入竞赛模式! 7554

Python 爬虫实战:全球咖啡期货市场数据采集与分析全攻略

通过本项目,我们实现了对全球咖啡期货市场数据的采集、处理和可视化,为市场分析和决策支持提供了数据基础。未来,可以进一步结合机器学习和深度学习技术,对咖啡期货价格进行预测和建模,提高市场分析的准确性和效率。

2201_76125261的博客 396

智能车图像处理16-进阶篇8--右环岛状态机与补线

这篇文章主要讲述智能车竞赛中如何判断右环岛并且进行状态补线。

taiyuezyh的博客 1万+

DP:完全背包问题

在完全背包问题中,每种物品有无限个可用,目标是在限定的背包容量内,选择物品使得总价值最大。动态规划通过将问题分解为子问题,利用子问题的解来构建最终解。完全背包问题具有最优子结构性质和重复子问题结构,非常适合用动态规划求解。通过对完全背包问题的深入探讨,我们了解了动态规划在解决这类问题中的重要性。完全背包问题在实际应用中非常广泛,例如货币兑换、资源分配和路径规划等。在解决过程中,我们学会了如何定义状态、确定状态转移方程,并通过优化空间复杂度提升算法效率。

2301_79969994的博客 1646

unitree-G1外接 USB 麦克风完整配置指南

首先,将type-c麦克风插入G1机器人的USB口后,记录下USB麦克风的卡号(card)和设备号(device),通常显示为 card 1: Device [USB Audio Device]

m0_47999117的博客 600

【动态规划】完全背包问题应用

【动态规划】完全背包问题应用

fight_p的博客 3065

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

完全背包问题(动态规划)

完全背包问题 题目: 有 N 种物品和一个容量为 V 的背包,每种物品都有无限件可用。第 i 种物品的费用是 c[i],价值是 w[i] 。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 一、验证动态规划求解的可行性 这个问题可以不可以像01背包问题一样使用动态规划来求解呢?来证明一下即可。 首先,先用反证法证明最优化原理: 假设完全背包...

但行好事,莫问前程 6143

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

动态规划——完全背包问题

聪明人都会点进来学习!!动态规划看这一篇就够了!!!本文详细讲解了动态规划的核心思路(配有图片),还以经典问题——完全背包问题为例,先从基础解法开始讲解思路,再一步步优化(一维数组),带有完整代码(有详细注释),对于难以理解的地方还会举例讲解,还会和01背包问题对比思考,赶紧点进来学习吧!!!

yourgrandfather_的博客 3947

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

九大背包问题专题--完全背包问题(详解,最优解)

2.完全背包问题 和01背包问题的区别: 01背包1件物品只能选或者不选 完全背包问题:1件物品可以重复选多次,只要不超过总体积 题目: 问题: 有N件物品和一个容量是V的背包。 第i件物品的体积是vi,价值是wi。 求解将哪些物品装入背包,可使这些物品的总体积不超过背包的容量,且价值最大。 输入格式 第一行有两个整数,N,V用空格隔开,分别表示物品数量和背包容积。 接下来有N行,每行两个整数vi...

gl620321的博客 1万+

01背包问题&&完全背包问题

01背包问题 问题描述:有N件物品,每件物品的重量为w[i],价值为c[i],现有一个容量为V的背包,问如何选取物品放入背包中,使得物品的总价值最大。其中每种物品都只有1件。 输入: 5 8 //物品数 最大容量 3 4 //每件物品的重量 每件物品的价值 5 5 1 2 2 1 2 3 输出:10 完全背包问题 问题描述:有N件物品,每件物品的重量为w[i],价值...

jelly的博客 1798

背包问题/完全背包问题全解

核心代码 2:res[i][j] = Math.max(res[i-1][j],res[i-1][j-w[i]]+v[i]) 比较上一步(i-1)的最优方案,和这一步的最优方案谁的钱最多。k++) 就是可以加个w[i]物品,思想差不多,k 一开始是取0的意思是让res[i][j]进入else循环,得出res[i][j] = res[i][j-1](至少先继承一下前辈,如果k=1时不满足循环条件会没有数据),其他要注意的就是前面说的核心代码要注意乘以k的倍数。本人水平欠佳,望多多大佬指点!

qq_62691586的博客 675
上一篇: 01背包问题
下一篇: 第二讲 数据库系统结构抽象
Tander_Tang
博客等级 码龄11年 7粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值