背包DP问题(0/1背包,完全背包,多重背包,分组背包)

本文详细介绍了四种背包问题:0/1背包、完全背包、多重背包和分组背包。对于每种类型,阐述了问题模型、状态转移方程,并给出了具体的例子和代码实现。重点强调了0/1背包和完全背包中倒序循环的重要性,以及多重背包中使用贪心策略和单调队列的方法。
摘要由CSDN通过智能技术生成

0/1背包

问题模型

给定N个物品,其中第i个物品的体积为Vi,价值为Wi。有一个容积为M的背包。要求放入物品的总体积不超过M的情况下,总价值最高。

状态转移方程

F[i,j]表示从前i个物品里选出了总体积为j的物品放入背包,物品的最大价值和
请添加图片描述

例题

Description:

在N个数中找出其和为M的若干个数。先读入正整数N(1<N<100)和M(1<M<10000), 再读入N个正数(可以有相同的数字,每个数字均在1000以内), 在这N个数中找出若干个数, 使它们的和是M, 把满足条件的数字组合都找出来以统计组合的个数,输出组合的个数(不考虑组合是否相同)。

Input:

第一行是两个数字,表示N和M。
第二行起是N个数。

Output:

就一个数字,表示和为M的组合的个数。

Sample Input:

4 4
1 1 2 2

Sample Output:

3

容量M,每个元素容积N(i),价值N(i)
我们先按照状态方程来列出代码框架。
先求出基础问题,最大价值是否是M
普通算法空间复杂度为O(MN)

#include<iostream>
using namespace std;
#include<vector>
// 普通算法
void jichu()
{
   
	int N[6] = {
    1,1,2,2 };
	int M = 4;
	int DP[10][10];
	
	// DP数组初状态
	if (N[0] <= M)
	{
   
		DP[0][0] = N[0];
	}
	else
	{
   
		DP[0][0] = 0;
	}

	// 用i-1求i,i要从1开始
	// N[1]开始
	for (int i = 1; i <= 4; i++)
	{
   
		for (int j = 0; j <= M; j++)
		{
   
			DP[i][j] = DP[i - 1][j];
		}
		for (int j = N[i]; j <= M; j++)
		{
   
			DP[i][j] = max(DP[i][j], DP[i - 1][j - N[i]] + N[i]);
		}
	}
}

滚动数组降低开销
因为 i 阶段只与 i-1 阶段有关
我们把阶段i的状态存储在 i&1
空间复杂度为O(2M)

void gundong()
{
   
	int N[6] = {
    7,1,2,2 };
	int n = 4;
	int M = 6;
	int DP[2][10];

	if (N[0] <= M)
	{
   
		DP[0][0] = N[0];
	}
	else
	{
   
		DP[0][0] = 0;
	}

	for (int i = 1; i <= 4; i++)
	{
   
		for (int j = 0; j <= M; j++)
		{
   
			DP[i & 1][j] = DP[(i - 1
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值