01背包算法模板

01 背包二维数组模板

PS: dp[300][300]定义在主函数外面,数组中的每个元素初始化为0,w存储每件物品重量,v存储每件物品的价值,只需每次外循环用到,所以无需使用数组存储,dp[i][j]表示背包容量为j时,从0-i个商品中任取所能获得的最大价值。

ps:原理类似一张表格,每次新增加一个物品,依次遍历不同容量的背包,如果发不下,就继承上一层的价值,如果放得下就比较上一层的价值和(不含这个物品i的剩余情况下的最大价值+物品i的价值)谁大就选哪一个,注意:下标,0-10,0-4分别表示容量为1,2,3,4…10的背包,1-4表示第1,2,3,4个物品,这是个不断遍历的过程
01背包二位数组

// 不使用数组存储每个商品的体积和价值
#include<bits/stdc++.h>
using namespace std;
int dp[300][300];
int main(){
	int m,n; //m,n 输入的物品个数,背包容量 
	int w,v;
	cout << w << v << '\n';
	cin >> m >> n;
	for(int i = 1;i<=m;i++){
		cin >> w >> v;
		for(int j =1;j<=n;j++){
			j<w?dp[i][j] = dp[i-1][j]:dp[i][j] = max(dp[i-1][j],dp[i-1][j-w] + v);
		} 
	}
	cout << dp[m][n];
	return 0; 
}

01背包一维滚动数组优化模板

**PS:**dp[300]定义在主函数外面,默认每一个容量的背包大小的最大价值为0,数组尽量大一些,dp[j]表示背包容量为j时所能获得的最大价值。

ps:原理类似二维数组的解法,只是我们从最大的背包容量开始倒叙遍历,每一个物品也就是每一轮都会不断更新每一中容量背包的最大价值,直到更新完,我们只考虑背包容量>=新增物品体积的情况,这样我们每次都在覆盖dp[j]的值,只需要一维数组存储即可

在这里插入图片描述

// 不使用数组存储每个商品的体积和价值
#include<bits/stdc++.h>
using namespace std;
int dp[300];
int main(){
	int m,n;
	int w,v;
	cin >> m >> n;
	for(int i=1;i<=m;i++){
		cin >> w >> v;
		for(int j=n;j>=w;j--){
			// 内层和i没关系了,这是一个重新赋值的过程,每次换一个物品都会更新一次状态 
			dp[j] = max(dp[j],dp[j - w] + v);
		}
	}
	cout << dp[n];
} 
// 使用数组存储每个商品的体积和价值
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
	// dp[j]表示容量为j的背包所能装下物品的最大价值,定义在主函数外面,里面的值默认为0 
	// ps: i和j从1开始,0背包和0物品不包括。 
	int w[300],v[300],dp[300]; 
int main()
{
	int m,n; //分别表示物品个数和背包容量
	cin >> m >> n; 
	for(int i = 1;i <= m;i++)
		cin >> w[i] >> v[i]; //写入物品数据和背包容量数据
	// 直接外循环(物品)+内循环(背包)
	for(int i =1;i<=m;i++)
	{	// 倒叙遍历,优化一维数组 
		for(int j =n;j >=w[i];j--){
			dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
		}
	}
	cout << dp[n];
}

实例:洛谷B3873 [GESP202309 六级] 小杨买饮料

 
/*以价格为背包的容量
饮料的最大容量为背包的最大价值
dp[j]表示每个价格的背包所能获得的最大容量 */

#include<bits/stdc++.h>
using namespace std;
// 单个饮料的价格为100 
const int price_N = 100;

int dp[510*price_N+1];

int main() {
    int c, l;
    int N, L; // 物品个数和背包容量
    cin >> N >> L;
    for (int i = 1; i <= N; i++) {
        cin >> c >> l;
        for (int j =510*price_N ; j >= c; j--) { // 从背包容量开始递减
        if (dp[j - c] != -1) {  //判断数组是否被初始化
               dp[j] = max(dp[j], dp[j - c] + l);
            }
        }
    }

    int ans = -1;
    for (int i = 1; i <= 510*price_N; i++) {
        if (dp[i] >= L) {
            ans = i;
            break;
        }
    }

    ans == -1 ? cout << "no solution\n" : cout << ans << '\n';

    return 0;
}

Ps:在做这道题的时候,遇到了一些bug,在动态规划中使用 -1 作为未初始化的标志是一个常见的约定,我将数组定义在主函数外面,他的值都是0,但是注意,这个时候的数组并没有被真正的初始化,加上这个未初始化的判断条件至关重要!

参考资料及相关链接

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值