01背包

01背包

01背包题目

给了很多个物品,W和V是两个数组,第i个物品重量是W[i],价值是V[i]。背包最大承受重量为n。如何让这个背包装的价值最大。

01背包就是每个物品只有一件。定义一个和(物品总个数+1)的数组,当判断出这个物品需要装进去时候就置为1,不装进去置为0。这个就是这个数组。这也是为啥叫做01背包。

粘贴一个题目过来

int W[6] = {0 , 2 , 5 , 3 , 10 , 4}; //价值

int V[6] = {0 , 1 , 3 , 2 , 6 , 2}; //物体重量

int bagW = 12;    //背包承受重量的上限

 

解题思路

我说的不专业,就题论题把。

简单来说,就是用一个二维数组来解决问题。

我们知道题目给了背包承受重量的上限为n,我们用二维数组的每列保存上限为1到n的情况。

二维数组每一行对应目前存在什么物品,这里包含每行上面所有的物品不包括下面的物品。

二维数组中的每个格子元素就是对应当前存在什么物品,背包最大承受重量的上限所对应的最大价值。

 

第二个就是判断这个物品是不是应该装进去,装还是不装,这是这个问题的关键。

下面这个方程就是判断装与不装的

if(j>=w[i])
    m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);

else
    m[i][j]=m[i-1][j];

 

int V[6] = {0 , 2 , 5 , 3 , 10 , 4}; //价值

int W[6] = {0 , 1 , 3 , 2 , 6 , 2}; //物体重量

int bag = 12;    //背包承受重量的上限

 

针对这个题目画出来的二维数组

 

 0123456789101112
00000000000000
10222222222222
20225777777777
302357810101010101010
402357810121315171820
502467911121416171921

我们从w[1][1]开始看,因为最初只有物品1且背包上限随着列的 增加我们依次递增。但是我们每个物品都是只有一个。因此,第一行就是从出现2之后后面都为2。

我们要清楚的是每个格子对应的是什么东西,

存在该行以上的物品,该列所表示的背包上限,所对应的最大价值。

我们看w[2][3] 是怎么算出来等于5的。

当背包上限为3时候,第二个物品是对应是(3,5)重量为3价值为5。

执行过程为先判断背包上限能装下物品2不,发现可以就执行if语句

if中拿w[1][0]+5 和 w[1][2]比较大小,大的那填入进去,所以w[2][3] = 5;

主要这一步最关键,它相当于我发现我背包承受重量上限(这里上限指的是每列)大于我这个物品重量可以装下,好那我先回退到没有我这个物品(也就是上一行),我能塞下这个物品的重量(也就是回退对应该物品的重量的列数)所对应的的最大价值+这个物品对应的价值 和我上一行当前列数价值相比较,谁大填谁。

每一行都这么处理就,发现到了右下角就是我们想要求得的最大价值。

 

简单代码表达下意思也好懂,主要是懂意思就好了

int main()
{
	int V[6] = {0,2,5,3,10,4};
	int W[6] = {0,1,3,2,6,2};

	int m[6][13] = {0};
	for(int i=1; i<6; i++)
	{
		for(int j=1; j<13; j++)
		{
			if(W[i]>j)
			{
				m[i][j] = m[i-1][j];
			}
			else
			{
				m[i][j] = max(m[i-1][j],m[i-1][j-W[i]]+V[i]);
			}
			cout<<m[i][j]<<" ";
		}
		cout<<endl;
	}

	return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值