完全背包问题

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>



智能问数产品背后的Agent技术揭秘:从任务分解到工具调用的完整流程 本文深入解析智能问数产品背后的Agent技术,从任务分解到工具调用的完整流程。通过大模型驱动的语义理解和动态工具调度,Agent系统能高效处理复杂数据分析需求,显著提升响应速度和准确率。文章详细介绍了模块化架构、任务分解机制、动态工具调用及双通道记忆系统等核心技术,展示了大模型时代的新型数据分析范式。 阅读详情

相关推荐

告别迷茫!用C#和Windows.Devices.Bluetooth搞定BLE设备连接与数据收发(附完整代码)

本文详细介绍了如何使用C#和Windows.Devices.Bluetooth命名空间实现BLE设备连接与数据收发。从开发环境配置到设备扫描、服务发现、数据通信及资源管理,提供完整代码示例和实战技巧,帮助开发者快速掌握低功耗蓝牙开发,解决连接稳定性和异常处理等常见问题。

weixin_29248653的博客 505

完全背包理论基础

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

qq_63953838的博客 147

零基础也能搞定!华为USG6000V防火墙WEB管理界面开启教程

本文详细介绍了华为USG6000V防火墙WEB管理界面的开启教程,从环境准备、网络配置到防火墙初始化,逐步指导用户完成图形化管理界面的搭建。特别适合零基础用户快速掌握企业级防火墙的可视化操作,提升安全管理效率。

grape的博客 787

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

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

52Herzt的博客 5527

【HarmonyOS 5】鸿蒙APP使用【团结引擎Unity】开发的案例教程

以下是基于团结引擎开发鸿蒙Unity应用的详细案例教程,整合环境配置、工程适配、跨语言通信等核心环节。

2201_75709314的博客 2483

有关SPSS中Fisher精确检验无法进行的解决方法(由于无法打开临时文件,因此无法进行计算)

最近在帮一个四年生完成她的毕业论文,在用SPSS进行R×C表检验的时候,发现Fisher精确检验的结果无法显示,提示为“由于无法打开临时文件,因此无法进行计算”,大概像下图一样。 (这图是从网上找的) 然...

chuyang37的博客 3万+

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

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

Conner7的博客 7444

PLS-PM with R 偏最小二乘路径建模 (R语言)

1. 引入 1.1. 安装plspm包 plspm 是一个用于执行偏最小二乘路径建模分析的 r 程序包。 在 CRAN 上可以免费下载: Http://cran.r-project.org/web/packages/plspm/index.html. 此后,通过以下代码在r中安装并加载该程序包即可。 install.packages("plspm") library("plspm") 2. 一些简单概念 2.1. 潜变量和观测变量 不少变量如满意度、成功指数是无法通过观测得到

Wowlittlemoon的博客 1万+

完全背包问题(动态规划(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

Windows 2000系统下载与全套镜像安装:从镜像校验到驱动兼容性实战指南

操作系统镜像文件是安装系统的核心载体,其完整性直接影响部署成败。哈希校验作为验证文件一致性的基础手段,能有效避免因镜像损坏导致的安装中断。对于已停止支持的操作系统,如Windows 2000,其镜像获取与安装更具挑战性,但它在工业控制、专用终端及怀旧技术研究中仍有不可替代的价值。通过理解镜像命名规则、服务包等级(如SP4)及引导方式,结合虚拟机或老硬件平台,可以顺利完成部署。同时,驱动兼容性是老系统运行的关键瓶颈,需针对性解决网卡、显卡等外设驱动问题。本文从镜像下载、校验到安装配置,系统梳理了Windows

weixin_32050773的博客 347

配置 SAP Fiori 服务的 ICF 节点:从 SICF 激活到访问链路打通的完整实践

在SAP Fiori项目实施中,ICF节点配置是关键前置条件却常被忽视。ICF(Internet Communication Framework)作为HTTP请求入口,需要通过SICF事务码激活相关服务节点,否则即使应用开发完善,用户仍可能遇到页面无法访问等问题。典型问题表现为:磁贴可点击但页面空白、资源加载失败等。激活路径主要涉及三组节点:bsp分支下的管理入口、ui5_ui5分支下的应用资源,以及public/bc下的公共资源。项目实施中需特别注意同名服务在不同分支下的差异化作用,确保完整链路通畅。IC

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 267

DP:完全背包问题

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

2301_79969994的博客 1646

AMBA-CHI协议详解(二)

读事务,写事务,原子事务,Stash事务,Dataless事务,DVM事务,Retry事务。

Crazzy_M的博客 6656

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

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

fight_p的博客 3065

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

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

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

但行好事,莫问前程 6143

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

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

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

yourgrandfather_的博客 3947

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

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

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、付费专栏及课程。

余额充值