(C++)0-1背包问题(动态规划)

写在所有的前面:

本文采用C++实现代码

题目说明

题目:0-1背包问题

题目出处

广西大学oj
22级《算法设计与分析》第二次课堂作业
https://oj.gxu.edu.cn/contest/625/problem/0003

题目描述Description

背包问题是指有N件物品和一个容量为W的背包。第i件物品的价值是v,需要占用的容量是w。
求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
而0-1背包问题是指可选择的物品每种仅有一件,可以选择不装入某物品,即0;或选择装入某物品,即1

输入Input

第一行为正整数N,代表有N件物品可选
第二行为正整数W,代表背包容量
第三行为N个数,分别代表第1到N个物品的价值v,以空格隔开
第四行为N个整数,分别代表第1到N个物品需要占用的容量w,以空格隔开

输出Output

输出为根据输入条件能装入的最大价值

样例Sample

输入:

5
15
4 2 6 2 8
12 1 1 1 4

输出:

18

限制Hint

解答说明

方案1:动态规划

解题思路

参考:Yngz_Miao《【动态规划】01背包问题(通俗易懂,超基础讲解)》
https://blog.csdn.net/qq_38410730/article/details/81667885
总共n个物体,W背包容量
通过 sumv[i][j] 记录放前 i 件物品,背包容量为 j 时,所拥有的最大总价
遍历每一个 i 和 j 来实现对 sumv 的填充
最后输出 sumv[n][W] 即可

一般情况

当物品 i 无法被装进去时j < w[i],和装上一件时一样sumv[i][j] = sumv[i - 1][j];
否则掏出对应体积的物品,查看当时的最大总价 + 当前物品价值 与 装上一件时相比,哪个更总价更大sumv[i][j] = max(sumv[i - 1][j], sumv[i - 1][j - w[i]] + v[i])

特殊情况

初始化:没有物品( i == 0 )和没有背包容量( j == 0 )时,sumv 为 0

代码实现

#include<iostream>
using namespace std;

const int N = 100;//常量
int n, W;//物品个数,背包容量
int w[N], v[N];//物品的体积,价值
int sumv[N][100 * N];//最大总价,max[i][j] 代表放前 i 件物品,背包容量为 j 时

int main()
{
	//输入数据
	scanf("%d%d", &n, &W);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &v[i]);
	}
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &w[i]);
	}
	//计算最大总价值
	for (int i = 1; i <= n; i++) //放入前 i 件物品
	{
		for (int j = 1; j <= W; j++) //背包容量增大为 j
		{
			if (j < w[i])//装不进去
				sumv[i][j] = sumv[i - 1][j];//和装上一件时一样
			else//装得进去
				//掏出对应体积的物品,查看当时的最大总价 + 当前物品价值 与 装上一件时相比,哪个更总价更大
				sumv[i][j] = max(sumv[i - 1][j], sumv[i - 1][j - w[i]] + v[i]);
		}
	}
	//全部物品全部容量时最大价值
	printf("%d", sumv[n][W]);

	return 0;
}

其他解释

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值