关于简单的0-1背包问题

        在上完这节算法课后,觉得自己应该写一份关于0-1背包问题的见解,(才疏学浅)如果有原理、代码问题请及时告知,谢谢大家。

目录

一·首先0-1背包是什么?

二.什么是动态规划?

三.核心思路

四.实例解释

五.代码演绎



一·首先0-1背包是什么?

        所谓的0-1背包,我个人的见解是:有n个物品,各自都有自己的重量和价值,有一个容量为c的背包,问:如何让背包里装入的物品具有最大的价值总和?

二.什么是动态规划?

        动态规划其实是大问题拆分成小问题,通过寻找大问题与小问题的递推关系,解决一个个小问题,最终达到解决原问题的效果。规划则具有记忆性,通过填写表把所有已经解决的子问题答案纪录下来,在新问题里需要用到的子问题可以直接提取,避免了重复计算,从而节约了时间,所以在问题满足最优性原理之后,用动态规划解决问题的核心就在于填表,表填写完毕,最优解也就找到。

三.核心思路

(1)首先依据题目要求确定一个状态变量:f[i][j]表示第i件物品放入容量为j的背包的最大价值

(2)此问题的特点是第i个物品我们到底是放还是不放?

(3)如果j<w[i],表示背包的容量不够,此时放入背包物品的最大价值:f[i][j]=f[i-1][j]   /*即当容量=j时,第i个放不下了,只能放前i-1个物品的最大价值*/

(4)如果j>=w[i],表示背包的容量还没有被占满,此时考虑一个问题,即上面提到过的(2)我们到底是能不能第i个物品呢?

<1>不能放,则和(3)一样,只放前i-1个物品,此时最大价值为:f[i][j]=f[i-1][j] 

<2>可以放,则f[i][j]=f[i-1][j-w[i]]+v[i]   /*表示第i件物品如果放。则最大价值=前i-1个物品的价值+第i个物品的价值。前i-1个物品的价值=f[i-1][j-w[i]].其中j-w[i]=背包能承受总重量c-第i个物品重量。v[i]便是第i个物品的价值。*/

最后,综上所述,我们取得背包所能承受最大容量的最大价值:

 f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i])

四.实例解释

编号1234
重量2345
价值3456

物品/容量012345678
0000000000
1003333333
2003447777
3003457899
40034578910

下面解释一下上面表格是如何填写的

EX:两个公式:

1 f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i])j>=w[i]
2f[i][j]=f[i-1][j]   j<w[i]

取f[1][1],   i=1,j=1,w[1]=2,v[1]=3,此时j<w[1],  采用公式2,带入即得0;

取f[1][2],i=1,j=2,w[1]=2,v[1]=3,此时j=w[1],采用公式1,带入即得3;

取f[1][3],  i=1,j=3,w[1]=2,v[1]=3,此时j>w[2],   采用公式1,带入即得3;

......

以此类推,我们能得出表中所有数据,从而得到max价值为f[4][8]=10.表示:四件物品放入背包容量等于8的最大价值为10.

五.代码演绎

核心代码如下:

void Max() {				
	for (int i = 1; i <= 4; i++) {
		for (int j = 1; j <= 8; j++) {
			if (j < w[i])
				f[i][j] = f[i - 1][j];
			else
				f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[i]);
		}
	}
}
void bag(int i, int j) {			
	if (i >= 0) {
		if (f[i][j] == f[i - 1][j]) {
			x[i] = 0;
			bag(i - 1, j);
		}
		else if (j - w[i] >= 0 && f[i][j] == f[i - 1][j - w[i]] + v[i]) {
			x[i] = 1;
			bag(i - 1, j - w[i]);
		}
	}
}
//计算价值

完整代码如下:

#include<iostream>
using namespace std;
#include <algorithm>

int w[5] = { 2,3,4,5,6};			
int v[5] = { 3,4,5,6,7 };		
				        
int f[5][9] = { { 0 } };			        
int x[5];	//最优解				       

void Max() {				
	for (int i = 1; i <= 4; i++) {
		for (int j = 1; j <= 8; j++) {
			if (j < w[i])
				f[i][j] = f[i - 1][j];
			else
				f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[i]);
		}
	}
}

void bag(int i, int j) {			
	if (i >= 0) {
		if (f[i][j] == f[i - 1][j]) {
			x[i] = 0;
			bag(i - 1, j);
		}
		else if (j - w[i] >= 0 && f[i][j] == f[i - 1][j - w[i]] + v[i]) {
			x[i] = 1;
			bag(i - 1, j - w[i]);
		}
	}
}

void output() {
	for (int i = 0; i < 5; i++) {			
		for (int j = 0; j < 9; j++) {
			cout << f[i][j] << ' ';
		}
		cout << endl;
	}
	cout << endl;

	for (int i = 0; i < 5; i++)		
		cout << x[i] << ' ';
	cout << endl;
}

int main()
{
	Max();
	bag(4, 8);
	output();
	return 0;
}

以上就是我对0-1背包的个人见解,也是我第一次写CSDN,大家有问题都可以提出来,我及时修正。

                                                                                                                              ---ssss

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值