01背包问题(模板)

01背包是给你一个背包,告诉你背包的容量,有若干物品,每个物品有自己的重量和价值,每个物品只有一个,问要怎么样选才能使背包的价值最大

#include<iostream>
using namespace std;
#define N 6
#define W 21
int B[N][W] = { 0 };//初始化为0    N表示是否偷物品的下标,W表示背包容量
//这个二维数组最后计算出来的是钱n个物品,容量为w的背包能装的最大价值
int w[6] = { 0,2,3,4,5,9 };//物品的重量
int v[6] = { 0,3,4,5,8,10 };//物品的价值
void knapsack() {
	int k, c;//k表示第k个商品 c表示背包容量
	for (k = 1; k <= N; k++) {
		for (c = 1; c <= W; c++) {
			if (w[k] > c) {//当前物品重量比先能容纳的还大
				B[k][c] = B[k - 1][c];
			}
			else {
				int value1 = B[k - 1][c - w[k]] + v[k];//偷,下标减一,容量减去该物品的重量 表示B[k - 1][c - w[k]]最大的价值
				int value2 = B[k - 1][c];//不偷,下标减一,容量不变
				if (value1 > value2) {
					B[k][c] = value1;
				}
				else {
					B[k][c] = value2;
				}
			}
		}
	}
}
int main() {
	knapsack();
	cout << B[5][20] << endl;//这里就相当于前五个物品,最大容量为20的背包最大价值是多少
	return 0;
}

参考:正月点灯笼

滚动数组优化

经过观察可以发现,上面那种能够的得到的答案更加地广泛普遍,例如:能够输入任意前n个物品在w容量下的最大价值,但是数组的二维空间开销巨大,而我们也不需要哪些答案,一般我们输入的数据都要用到,所以前面的哪些答案对我们来说是多余的,可以把二维数组降维为一维数组

二位数组:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

一维数组滚动优化:

状态转移方程:dp[j]=max(dp[j],dp[j-w[i]]+v[i])

//倒过来循环

倒过来遍历的原因:从上面的递推公式中可以看出,二位数字的结果与上一行的数据有关,滚动的数组优化没有了行,如果正序,前面的数据可以已经被改多次了,已经不是我们要的值了

//dp[j]:相当于dp[i-1][j]

//dp[j-c[i]]:相当于dp[i-1][j-w[i]]
为什么要逆序请看0-1背包:使用滚动数组时为何要逆序枚举_aidway的专栏-CSDN博客

#include<iostream>

#include<algorithm>

using namespace std;

/*

二位数组:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])

一维数组滚动优化:

状态转移方程:dp[j]=max(dp[j],dp[j-w[i]]+v[i])

*/

int w;//背包容量

int dp[20010];

int n;//n各个物品

int wi, vi;//wi重量,vi价值

int main() {

cin >> w >> n;

for (int i = 1; i <= n; i++) {

//倒过来循环

//dp[j]:相当于dp[i-1][j]

//dp[j-c[i]]:相当于dp[i-1][j-w[i]]

cin >> wi >> vi;

for (int j = w; j >= wi; j--) {

//每个物品选和不选的两个状态

dp[j] = max(dp[j], dp[j - wi] + vi);

}

}

cout << dp[w] << endl;



return 0;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值