【未写完】0/1背包问题的三种算法思想分析(贪心算法、动态规划、分支限界法)

本文有引用其他作者的文章,请看对应算法后的原文链接

1贪心算法

C=150C=150, 最大承重

wi=[35,30,60,50,40,10,25]wi=[35,30,60,50,40,10,25],每个物品的重量

pi=[10,40,30,50,35,40,10]pi=[10,40,30,50,35,40,10],每个物品的价格

关键在于子问题的定义,本例,我么可以将子问题定义为,在选取某一物品(wiwi)放入背包以后,在背包容量还有C′:=C−wiC′:=C−wi的情况下,选择下一个物品放入背包。

 

如何选择每一次子问题的所需确定的物品呢?这正是贪心策略的选择问题了。对于本题,常见的贪婪策略有三种,

1.根据物品价值选择,每次都选价值最高的物品

[4, 2, 6, 5]-> 130(总重量),165(价值)

 

2.根据物品重量选择,每次都选最轻的

[6, 7, 2, 1, 5] -> 140(总重量),155(总价格)

 

3.根据价值密度(也即性价比),每次都选性价比最高的

性价比:[0.286, 1.333, .5, 1., .0875, 4., 1.2]

[6, 2, 7, 4, 1] -> 150(总重量),170(总价格)

 

该算法原文https://blog.csdn.net/lanchunhui/article/details/49962709


2动态规划

 

实例和运行结果
对应的数组M

Java关键代码:

	/*计算最优值方法
     * Knapsack(数量n,背包容量c,重量列表w,价值列表v,数组M){}
     * return:无
     * 说明:计算并构建0-1最优值M数组
     * 
     * i,j:循环变量 
     * Jmax:背包已用容量
     */
	public static void Knapsack(int n,int c,int w[],int v[],int m[][]){
		int i,j;
		int Jmax = Min(w[n]-1,c);//找到最后物品不能存放的容量区间上限
		for(i=0;i<=Jmax;i++)//最后一个物品不能存放的区间,价值设为0
			m[n][i]=0;
		for(i=w[n];i<=c;i++)//可以存放,填入最后一个物品价值
			m[n][i]=v[n];
		for(i=n-1;i>0;i--){
			Jmax = Min(w[i]-1,c);//找到当前背包已用容量
			for(j=0;j<=Jmax;j++)//填入背包已用容量的价值
				m[i][j]=m[i+1][j];
			for(j=w[i];j<=c;j++)//将原有物品的价值和加入物品后的总价值中的最大指,填入背包未用容量
				m[i][j]=Max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
		}
		m[0][c] = m[1][c];//先将原最大价值设为当前最大价值
		if(c>=w[0])//如果还能装下1号物品,填入原最大价值和加入1号物品后的总价值中的最大值
			m[0][c]=Max(m[0][c],m[1][c-w[1]]+v[i]);
	}
	
	/*生成最优解序列方法
     * Traceback(数量n,背包容量c,重量列表w,数组M,解序列数组X){}
     * return:无
     * 
     * 
     * i:循环变量 
     * Jmax:背包已用容量
     */
	public static void Traceback(int n,int c,int w[],int m[][],int x[]){
		for(int i=0;i<n;i++){
			if(m[i][c]==m[i+1][c])//如果当前总价值==上一轮总价值
				x[i]=0;           //当前物品未加入背包
			else{
				x[i]=1;           //否则,当前物品加入背包
				c-=w[i];//背包容量减去当前物品总量,供下一循环返回到添加物品时的容量
			}
		}
		if (m[n][c]!=0)//判断最后一个物品重量是否超过背包容量
			x[n] = 1;//没有超过,则被加入背包
		else
			x[n] = 0;//超过,则被加入背包
	}

 


3分支限界法

例:0/1背包问题。假设有4个物品,其重量分别为(4, 7, 5, 3),价值分别为(40, 42, 25, 12),背包容量W=10。首先,将给定物品按单位重量价值从大到小排序,结果如下:

   

价值上界:用贪心算法求背包问题

4*10+6*6=76

价值下界:用贪心算法求0/1背包问题(选价值最高且能够存放的物品)

40+25=65

目标函数:

通过这个函数得到的一个和待处理节点表:

解空间树

待处理节点表

1(100)

2(76)、3(60)

5(70)

6(69)、7(64)

9(65)

具体步骤

(1)在根结点1,没有将任何物品装入背包,因此,背包的重量和获得的价值均为0,根据限界函数计算结点1的目标函数值为10×10=100;

(2)在结点2,将物品1装入背包,因此,背包的重量为4,获得的价值为40,目标函数值为40 + (10-4)×6=76,将结点2加入待处理结点表PT中;在结点3,没有将物品1装入背包,因此,背包的重量和获得的价值仍为0,目标函数值为10×6=60,将结点3加入表PT中;

(3)在表PT中选取目标函数值取得极大的结点2优先进行搜索;

(4)在结点4,将物品2装入背包,因此,背包的重量为11,不满足约束条件,将结点4丢弃;在结点5,没有将物品2装入背包,因此,背包的重量和获得的价值与结点2相同,目标函数值为40 + (10-4)×5=70,将结点5加入表PT中;

(5)在表PT中选取目标函数值取得极大的结点5优先进行搜索;

(6)在结点6,将物品3装入背包,因此,背包的重量为9,获得的价值为65,目标函数值为65 + (10-9)×4=69,将结点6加入表PT中;在结点7,没有将物品3装入背包,因此,背包的重量和获得的价值与结点5相同,目标函数值为40 + (10-4)×4=64,将结点6加入表PT中;

(7)在表PT中选取目标函数值取得极大的结点6优先进行搜索;

(8)在结点8,将物品4装入背包,因此,背包的重量为12,不满足约束条件,将结点8丢弃;在结点9,没有将物品4装入背包,因此,背包的重量和获得的价值与结点6相同,目标函数值为65;

(9)由于结点9是叶子结点,同时结点9的目标函数值是表PT中的极大值,所以,结点9对应的解即是问题的最优解,搜索结束。

该算法原文http://www.cnblogs.com/FreeAquar/archive/2012/06/21/2291436.html

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值