动态规划——01背包问题

这里有我在B站上的讲解,感兴趣的小伙伴可以去看一下
1267:【例9.11】01背包问题

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 13138 通过数: 8070
【题目描述】
一个旅行者有一个最多能装 M 公斤的背包,现在有 n 件物品,它们的重量分别是W1,W2,…,Wn,它们的价值分别为C1,C2,…,Cn,求旅行者能获得最大总价值。

【输入】
第一行:两个整数,M(背包容量,M≤200)和N(物品数量,N≤30);

第2…N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。

【输出】
仅一行,一个数,表示最大总价值。

【输入样例】
10 4
2 1
3 3
4 5
7 9
【输出样例】
12


1 收先我们来了解一下题意
在一个体积为m的背包里,n个物体当中选择物品,使背包中的物品总价值最大。

2。模拟样例
由题意知道,我们要尽可能的.找到总价值最大的选择,
我们可以看出,选择第二个和第四个是最大的,体积和为10满足条件,价值为12 是最大价值。
其他的,比如第一个、第二个、第三个,体积和为9满足条件,总价值为1+3+5=9,小于12
我们可以看出,没有其他的组合的总价值大于12,所以12为我们的最终结果。


3.分析
我们有一种认识,我们要做的就是找到最优方案,我们要京可能的利用空间,并且尽可能的使放到背包里的总价值最大
有这种认识,但是做的时候却很费解,因为我们不能用for循环枚举所有的可能,那样的话时间复杂度为(N!),是一定会时间超限的


4.策略
我们思前想后终于想到了一种方法,动态规划
方案,我们每次仅选择前i个物品,且体积不超过j的方案,并求最优解。
下面先附上以这种方法模拟的步骤
动态规划——01背包问题_第1张图片
经过我们的样例模拟后,我们发现,我们的策略是行的,下面,我们要做的就是写出一般方程


一般方程:
通过样例模拟我们知道,当到前i个物品的时候,无非就两种情况
1、不选第i个物品,也就是前i-1个物品的最优解,
2、选第i个物品,当选第i个物品的时候,如何的出它的方程呢。
我们这么直接想,很难想到这么抽象的方程,所以我们稍微变换一下思路
既然我们一定选择第i个物品,我们不如先不看第i个物品,将第i个物品所占的体积去掉,剩下的空间交给前i-1个物品中的某一些物品去争去吧。所以不算第i个物品,剩余空间所有的价值为***f[i-1][j-v[i]]***,那么我们在加上第i个物品是不是就是选第i个物品的结果了。
对的,就是这个结果***f[i][j]=f[i-1][j-v[i]]+w[i];***
则我们就很容易的得出了最终的方程式。
即: f[i][j]=max(f[i-1][j], f[i-1][j-v[i]]+w[i]
下面是这个方程的图片推导,有兴趣的可以看一下。
动态规划——01背包问题_第2张图片

好,到了最激动人心的时刻了,代码来喽

源代码

语言: G++     用户名: RookieToFly     题号: 1267

#include 

using namespace std;

const int N = 210;

int n, m;
int v[N], w[N];
int f[N][N];

int main(){
	cin >> m >> n;//m表示背包容量,n表示物体个数
	for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];//读入数据
	
	for (int i = 1; i <= n; i ++ ){//表示只选择前i个物体
		for (int j = 1; j <= m; j ++ ) {//表示体积
			f[i][j] = f[i -1][j];
			if (j - v[i] >= 0)//体积要大于等于0
			f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
			//第一个表示不选第i个物品,第二个表示选则第i个物品
		}
	}
	cout << f[n][m] << endl;//表示选择前n个物品,体积为m的最大价值
	
	return 0;
 }

如果大家有什么看不懂的可以回复我,我会为大家解释的
如果大家有什么补充的,也可以回复我。
那个,关于动态规划的优化,优化为一维数组的我会在后面有空的时候给大家附上的;
那就感谢您的观看喽

如果没有看懂的,或者有一些疑惑的可以观看我在B站上的视频,记得点赞哦。
这里是链接:
添加链接描述

你可能感兴趣的:(算法学习)