对于0-1背包的问题的初步了解

在B站上看了一个关于0-1背包问题的视频,让我对0-1背包有了自己初步的了解,可能不像一些大佬那样流弊哄哄,但是也是个小可爱了。

首先,我们通过一个例题来看看。
题目的大概意思是,有一个小偷拿着麻袋去商场偷东西,小偷的背包大小为W(即小偷只能偷重量之和为小于等于W的物品),商场里有如下表格种类的物品分别对应物品的重量和对应物品的价格,问小偷能偷到的物品的价格之和最大为多少?

标号重量(wk价格(vk
123
234
345
458
5910

为了方便起见,我们将物品的标号从1开始。
我们用一个二维数组B[k][c]来记录当前偷到的价格(其中k表示前k个物品,c表示剩下多少空间)。我们很容易发现,当第k件物品太重(wk>c)时无法偷走,这时候B[k][c]=B[k-1][c]。当第k件物品没有那么重可以放进包里的时候,这时候我们要考虑,偷还是不偷的问题,这个时候我们就要比较是偷了的价值大,还是不偷的价值大,那么显然,B[k]=max(B[k-1][c-wk]+vk,B[k-1][c])。
综合以上所述,我们可以得到一个递推表达式:
在这里插入图片描述
整个递归过程,我们可以以一个分支为例,简单画一下:
在这里插入图片描述
旁边的分支我们可以自己拿笔画,可以发现,B[5][20]=26,也就是这道题的实际答案。

#include<stdio.h>
#include<string.h>
//假设包的重量和商品的种类都不超过100
int B[105][105]; 
int main()
{
	int w[105];//商品的重量 
	int v[105];//商品价值 
	int N,W;//商品种类、背包重量 
	int k,c;
	memset(B,0,sizeof(B));
	memset(w,0,sizeof(w));
	memset(v,0,sizeof(v));
	printf("请分别输入商品的种类和背包的重量:"); 
	scanf("%d %d",&N,&W);
	printf("请分别输入%d种商品的重量和价值:\n",N); 
	for(int i=1;i<=N;i++)
		scanf("%d %d",&w[i],&v[i]);
	for(k=1;k<=N;k++)
		for(c=1;c<=W;c++)
			if(w[k]>c)//商品比背包容量重
				B[k][c]=B[k-1][c]; 
			else if(B[k-1][c-w[k]]+v[k]>B[k-1][c])
				B[k][c]=B[k-1][c-w[k]]+v[k];
			else B[k][c]=B[k-1][c];
	printf("%d\n",B[5][20]);
	return 0;
} 

运行结果如下:
在这里插入图片描述
完毕!

第一次学习背包、第一次写文章,有见者请多包涵,另外有错误希望指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值