0/1背包入门

本文深入探讨了背包问题的两种经典解决方法:蛮力法求幂集搜索和队列式分支界限法。通过具体实例,详细解释了每种方法的实现过程及代码实现,对比了它们的优劣,为读者提供了理解和解决背包问题的全面视角。

问题描述

有n个重量分别为w1 、 w2 、w3、w4···wn的物品,编号1~n,它们的价值为v1 、 v2 、v3、v4···vn。现有一容量为W的背包,求尽可能的把背包装满并使价值最大

下面不妨以n=4 W=6为例

物品编号重量价值
154
234
323
411

蛮力法–求幂集搜索

思路大概是用蛮力法找出n的所有幂集,然后遍历一遍,找到最优解

复杂度为O(2n)

#include<iostream>
#include<vector>
#include<stdio.h>
#include<map>
#include<algorithm>
using namespace std;
/**
	求解简单0/1背包问题
	2019-8-12 
*/
vector<vector<int> > ps;
void PSet(int n)  // 求1-n的幂集 
{
	vector<vector<int> > ps1;  // 子幂集 
	vector<vector<int> >::iterator it;
	vector<int> s;
	ps.push_back(s);    // 添加空集合元素
	for(int i=1;i<=n;i++)
	{
		ps1 = ps;
		for(it=ps1.begin();it!=ps1.end();it++)
			(*it).push_back(i);
		for(it=ps1.begin();it!=ps1.end();it++)
			ps.push_back(*it);	
	} 
} 

void Knap(int w[],int v[], int W)
{
	int count = 0;
	int sumw,sumv;
	int maxi,maxsumw=0,maxsumv=0;
	vector<vector<int> >::iterator it;
	vector<int>::iterator sit;
	printf(" 序号   选中物品     总重量    总价值     能否装入\n");
	for(it=ps.begin();it!=ps.end();it++)
	{
		printf(" %d\t",count++);
		sumw=sumv=0;
		printf(" {");
		for(sit=(*it).begin();sit!=(*it).end();sit++)
		{
			printf("%d ",*sit);
			sumw += w[*sit-1];  
			sumv += v[*sit-1];
		} 
		printf("}\t\t%d\t%d ",sumw,sumv);
		if(sumw<=W)
		{
			printf("能\n");
			if(sumv>maxsumv)
			{
				maxsumw = sumw;
				maxsumv = sumv;
				maxi = count-1;	
			} 
		}
		else cout << "否\n";
		//	count++;
	}
	printf("最佳方案为:");
	printf("选中物品");
	printf("{ ");
	for(sit=ps[maxi].begin();sit!=ps[maxi].end();sit++)
		printf("%d ",*sit);
	printf("},");
	printf("总重量:%d,总价值:%d\n",maxsumw,maxsumv); 	 
}
int main() 
{
	int n = 4, W = 6;
	int w[] = {5,3,2,1};
	int v[] = {4,4,3,1};
	PSet(n);
	printf("0/1背包解决方案\n",n);
	Knap(w,v,W);
	return 0;
}

队列式分支界限法

#include<iostream>
#include<queue>
using namespace std;
#define MAXV 20
int maxv = -9999; 
int bestx[20]; // 存放最优解,全局变量
int total = 1;
struct NodeType{
	int num;  // 结点编号 
	int i;    // 当前结点在搜索空间中的层次 
	int w;    // 当前结点的总权重 
	int v;    // 当前结点的总价值 
	int x[MAXV];  // 当前结点包含的解向量 
	double ub; // 上界 
}; 
int n =5,W = 6;
	int w[] = {0,5,3,2,1};
	int v[] = {0,4,4,3,1};
void bound(NodeType &e){  // 计算分支结点e的上界 
	int i=e.i+1;
	int sumw = e.w;
	double sumv = e.v; 
	while((sumw+w[i]<=W)&& i<=n){
		sumw += w[i];
		sumv += v[i];
		i++;
	}
	if(i<=n)
		e.ub = sumv+(W-sumw)*v[i]/w[i];
	else e.ub = sumv; 
} 

void EnQueue(NodeType e,queue<NodeType> &qu)
{
	if(e.i==n)
	{
		if(e.v>maxv)
		{
			maxv = e.v;
			for(int j=1;j<=n;j++)
				bestx[j] = e.x[j];
		}
	}
	else qu.push(e);
}
void bfs()
{
	int j;
	NodeType e,e1,e2;
	queue<NodeType> qu;
	e.i = 0;
	e.w = 0;
	e.v = 0;
	e.num = total++;
	for(j=1;j<=n;j++)
		e.x[j] = 0;
	bound(e);
	qu.push(e);
	while(!qu.empty())
	{
		e = qu.front();
		qu.pop();
		if(e.w+w[e.i+1]<=W)  // 剪枝:检查左孩子结点
		{
			e1.num = total++;
			e1.i = e.i+1;
			e1.w = e.w+w[e1.i];
			e1.v = e.v+v[e1.i];
			for(j=1;j<=n;j++)
				e1.x[j] = e.x[j];
			e1.x[e1.i] = 1;
			bound(e1);
			EnQueue(e1,qu); 
		} 
		e2.num = total++;
		e2.i = e.i+1;
		e2.w = e.w; 
		e2.v = e.v;
		for(j=2;j<=n;j++)
			e2.x[j] = e.x[j];
		e2.x[e2.i]= 0;
		bound(e2);
		if(e2.ub>maxv)
			EnQueue(e2,qu); 
	}
}
int main()
{
	
	bfs();
	printf("分支界限法求解0/1背包问题:\n X=[");
	for(int i=1;i<=n;i++)
		printf("%2d",bestx[i]);
	printf("],装入总价值为%d\n",maxv); 
	
	
	return 0;
}




未完待续~~

参考: 李春葆 .算法设计与分析(第二版)

【轴承故障诊断】加权多尺度字典学习模型(WMSDL)及其在轴承故障诊断上的应用(Matlab代码实现)内容概要:本文介绍了加权多尺度字典学习模型(WMSDL)在轴承故障诊断中的应用,并提供了基于Matlab的代码实现。该模型结合多尺度分析与字典学习技术,能够有效提取轴承振动信号中的故障特征,提升故障识别精度。文档重点阐述了WMSDL模型的理论基础、算法流程及其在实际故障诊断中的实施步骤,展示了其相较于传统方法在特征表达能力和诊断准确性方面的优势。同时,文中还提及该资源属于一个涵盖多个科研方向的技术合,包括智能优化算法、机器学习、信号处理、电力系统等多个领域的Matlab仿真案例。; 适合人群:具备一定信号处理和机器学习基础,从事机械故障诊断、工业自动化、智能制造等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①学习并掌握加权多尺度字典学习模型的基本原理与实现方法;②将其应用于旋转机械的轴承故障特征提取与智能诊断;③结合实际工程数据复现算法,提升故障诊断系统的准确性和鲁棒性。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注字典学习的训练过程与多尺度分解的实现细节,同时可参考文中提到的其他相关技术(如VMD、CNN、BILSTM等)进行对比实验与算法优化。
【硕士论文复现】可再生能源发电与电动汽车的协同调度策略研究(Matlab代码实现)内容概要:本文档围绕“可再生能源发电与电动汽车的协同调度策略研究”展开,旨在通过Matlab代码复现硕士论文中的核心模型与算法,探讨可再生能源(如风电、光伏)与大规模电动汽车接入电网后的协同优化调度方法。研究重点包括考虑需求侧响应的多时间尺度调度、电动汽车群有序充电优化、源荷不确定性建模及鲁棒优化方法的应用。文中提供了完整的Matlab实现代码与仿真模型,涵盖从场景生成、数学建模到求解算法(如NSGA-III、粒子群优化、ADMM等)的全过程,帮助读者深入理解微电网与智能电网中的能量管理机制。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的研究生、科研人员及从事新能源、智能电网、电动汽车等领域技术研发的工程人员。; 使用场景及目标:①用于复现和验证硕士论文中的协同调度模型;②支撑科研工作中关于可再生能源消纳、电动汽车V2G调度、需求响应机制等课题的算法开发与仿真验证;③作为教学案例辅助讲授能源互联网中的优化调度理论与实践。; 阅读建议:建议结合文档提供的网盘资源下载完整代码,按照目录顺序逐步学习各模块实现,重点关注模型构建逻辑与优化算法的Matlab实现细节,并通过修改参数进行仿真实验以加深理解。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值