0-1背包问题 C语言

本文探讨了使用回溯算法解决0-1背包问题,并介绍了备忘录方法进行优化。进一步讲解了动态规划的解决方案,强调在实际应用中,通过精简数据结构,甚至可能无需二维数组即可达到优化目的。最后,文章扩展到包含不同价值的物品,寻求可装入背包的最大价值问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 回溯算法
//cw表示已装重量和,i表示考察到第i个物品,w表示背包可承受重量,n表示物品个数,物品重量存储在数组a中,max表示当前最大值 
void bag(int i, int cw, int w, int n, int *item, int *max){
	if(cw==w || i==n){         //搜索剪枝 
		if(cw > *max){
			*max = cw;
		}
		return;
	}
	bag(i+1, cw, w, n, item, max);
	if(cw + item[i] <=w)
		bag(i+1, cw+item[i], w, n, item, max); 
}
  • 优化–备忘录解决方法
//cw表示已装重量和,i表示考察到第i个物品,w表示背包可承受重量,n表示物品个数,物品重量存储在数组a中,max表示当前最大值 ,mem[][cw]记录是否已经计算过,避免冗余计算
void bag(int i, int cw, int w, int n, int *item, int *max, int mem[][10]){
	if(cw==w || i==n){         //搜索剪枝 
		if(cw > *max){
			*max = cw;
		}
		return;
	}
	if(mem[i][cw]==1)
		return;
	mem[i][cw] == 1;
	bag(i+1, cw, w, n, item, max, mem);
	if(cw + item[i] <=w)
		bag(i+1, cw+item[i], w, n, item, max, mem); 
} 
  • 动态规划
//w表示背包可承受重量,n表示物品个数,物品重量存储在数组a中,state[n][w+1]记录每考察完一件物品state[][weight]是否存在 
int bag(int w, int n, int *item, bool state[][11]){
	state[0][0] = true;
	state[0][item[0]] = true;
	for(int i=1; i<=n-1; i++){
		for(int j=0; j<=w+1; j++){
			if(state[i-1][j]==true)
				state[i][j] = true;
		}
		for(int j=0; j<=w-item[i]; j++){
			if(state[i-1][j]==true)
				state[i][j+item[i]] = true;
		}
	}
	for(int i=w; i>=0; i--){
		if(state[n-1][i]==true)
			return i;
	}
}
  • 动态规划优化(就最后结果来看其实不需要二维数组)
//w表示背包可承受重量,n表示物品个数,物品重量存储在数组a中,state[w+1]记录每考察完一件物品state[weight]是否存在 
int bag(int w, int n, int *item, bool state[11]){
	state[0] = true;
	state[item[0]] = true;
	for(int i=1; i<=n-1; i++){
		for(int j=0; j<=w+1; j++){
			if(state[j]==true)
				state[j] = true;
		}
		for(int j=0; j<=w-item[i]; j++){
			if(state[j]==true)
				stat[j+item[i]] = true;
		}
	}
	for(int i=w; i>=0; i--){
		if(state[i]==true)
			return i;
	}
}
  • 0-1背包升级问题,加上物品含有不同的价值,求可装入的最大价值
int bag(int w, int n, int *item, int *value, int state[][11]){
	state[0][0] = 0;
	state[0][item[0]] = 0;
	for(int i=1; i<=n-1; i++){
		for(int j=0; j<=w+1; j++){
			if(state[i-1][j]>=0)
				state[i][j] = state[i-1][j];
		}
		for(int j=0; j<=w-item[i]; j++){
			if(state[i-1][j] >= 0){
				int v = state[i-1][j] + value[i];
				if(v > state[i-1][j+item[i]]){
					state[i][j+item[i]] = v;
				}
			}
		}
	}
	int max = -1;
	for(int i=w; i>=0; i--){
		if(state[n-1][i]>max)
			max = state[n-1][j];
	}
	return max;
}

利用动态规划原理进行求解 0-1背包问题 已知背包的容量为b,有n种物件,其价格依次为w1,w2,...,wn;其容量依次为v1,v2,...,vn。 现要求在背包允许的容量内,装的物件价值达到最大,其数字模型为: max z=1 x1 + 6 x2 + 18 x3 + 22 x4 + 28 x5 1 x1 + 2 x2 + 5 x3 + 6 x4 + 7 x5 <=11 xi=0,1 i=1,2,3,4,5 S(i,j)=max{S(i-1,j),S(i-1,j-vi)+wi} S(0,j)=0 j>=0 S(i,j)=负无穷 j<0 i=1,w1=1,v1=1 S(1,1)=max{S(0,1),S(0,1-1)+1}=1 S(1,2)=max{S(0,2),S(0,2-1)+1}=1 S(1,3)=...=S(1,11)=1 i=2,w2=6,v2=2 S(2,1)=max{S(1,1),S(1,1-2)+6}=1 S(2,2)=max{S(1,1),S(1,2-2)+6}=6 S(2,3)=max{S(1,3),S(1,3-2)+6}=7 S(2,4)=...=S(2,11)=7 i=3,w3=18,v3=5 S(3,1)=max{S(2,1),S(2,1-5)+18}=1 S(3,2)=max{S(2,2),S(2,2-5)+18}=6 S(3,3)=max{S(2,3),S(2,3-5)+18}=7 S(3,4)=max{S(2,4),S(2,4-5)+18}=7 S(3,5)=max{S(2,5),S(2,5-5)+18}=18 S(3,6)=max{S(2,6),S(2,6-5)+18}=19 S(3,7)=max{S(2,7),S(2,7-5)+18}=24 S(3,8)=max{S(2,8),S(2,8-5)+18}=25 S(3,9)=S(3,10)=...=S(3,11)=25 i=4,w4=22,v4=6 S(4,1)=max{S(3,1),S(3,1-6)+22}=1 S(4,2)=max{S(3,2),S(3,2-6)+22}=6 S(4,3)=max{S(3,3),S(3,3-6)+22}=7 S(4,4)=max{S(3,4),S(3,4-6)+22}=7 S(4,5)=max{S(3,5),S(3,5-6)+22}=18 S(4,6)=max{S(3,6),S(3,6-6)+22}=22 S(4,7)=max{S(3,7),S(3,7-6)+22}=24 S(4,8)=max{S(3,7),S(3,8-6)+22}=38 S(4,9)=max{S(3,7),S(3,9-6)+22}=29 S(4,10)=max{S(3,7),S(3,10-6)+22}=29 S(4,11)=max{S(3,7),S(3,11-6)+22}=40 i=5,w5=28,v5=7 S(5,1)=max{S(4,1),S(4,1-7)+28}=1 S(5,2)=max{S(4,2),S(4,2-7)+28}=6 S(5,3)=max{S(4,3),S(4,3-7)+28}=7 S(5,4)=max{S(4,4),S(4,4-7)+28}=7 S(5,5)=max{S(4,5),S(4,5-7)+28}=18 S(5,6)=max{S(4,6),S(4,6-7)+28}=22 S(5,7)=max{S(4,7),S(4,7-7)+28}=28 S(5,8)=max{S(4,8),S(4,8-7)+28}=29 S(5,9)=max{S(4,9),S(4,9-7)+28}=34 S(5,10)=max{S(4,10),S(4,10-7)+28}=35 S(5,11)=max{S(4,11),S(4,11-7)+28}=40
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值