代码随想录算法训练营 Day37 动态规划Ⅴ 完全背包 零钱兑换

动态规划

完全背包

纯的完全背包问题(只是背包)可以颠倒两次 for 循环的顺序

因为完全背包 dp 值由左边的状态推导而来的,两种遍历方法都能保证前面有数据

0-1 背包二维递推公式
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])

完全背包二维递推公式
dp[i][j] = max(dp[i - 1][j], dp[i][j - weight[i]] + value[i])

在于01背包是 dp[i - 1][j - weight[i]] + value[i] ,完全背包是 dp[i][j - weight[i]] + value[i])

主要原因就是 完全背包单类物品有无限个

题目

52. 携带研究材料(第七期模拟笔试)

对比 0-1 背包问题,将遍历顺序改为正序遍历(第二次顺序)

  1. Dp 表示容量 j 下的背包能装的最大价值

  2. 递推公式同 0-1 背包问题,比较空出来空间不拿这个物品和拿了这个物品的最大价值
    dp[i][j] = std::max(dp[i-1][j], dp[i-1][j-nums[i]] + value[i])

  3. 初始化顺序第一行与第一列(数据从第一行开始推导的)
    dp[i][0] = 0; dp[0][j]=dp[0][j-nums[0]] + value[0]

  4. 遍历顺序为物品 - 背包 (正序遍历一维数组)

  5. Dp 打印

cpp 复制代码
#include<iostream>
#include<vector>

int main() {
    int n = 0, v = 0;
    std::cin >> n >> v;

    std::vector<int> weight(n, 0);
    std::vector<int> value(n, 0);
    for (int i = 0; i < n; ++i) std::cin >> weight[i] >> value[i];
    // 初始化dp 单位j时最大的价值
    std::vector<std::vector<int>> dp(n, std::vector<int>(v+1, 0));
    for (int j = weight[0]; j <= v; ++j) dp[0][j] = dp[0][j - weight[0]] + value[0];
    
    // 遍历dp
    for (int i = 1; i < n; ++i) {
        for (int j = 0; j <= v; ++j) {
            if (j < weight[i]) dp[i][j] = dp[i-1][j];
            else dp[i][j] = std::max(dp[i-1][j], dp[i][j - weight[i]] + value[i]);
        }
    }

    std::cout << dp[n-1][v] << std::endl;
    return 0;
}

518. 零钱兑换 II - 力扣(LeetCode)

背包问题求组和,不强调顺序

  1. Dp 含义表示当前 i 个物品下装满 j 背包多少种方法

  2. 递推公式类似于 0-1 背包组合问题 dp[i][j] = dp[i-1][j] + dp[i][j-nums[i]]

  3. 初始化 dp[i][0]=1 第一行如果背包可以装下物品,则方法为 1,否则为 0

  4. 遍历顺序默认即可先物品后背包(可以颠倒,一维情况不同)

一维情况下不能颠倒,先遍历物品再遍历背包求排列数,先遍历背包再遍历物品求组合数

  1. 打印 dp
cpp 复制代码
int change(int amount, vector<int>& coins) {
	int bagSize = amount;

	// dp数组定义 在i个物品下装满j由多少种方法
	std::vector<std::vector<uint64_t>> dp(coins.size(), std::vector<uint64_t>(bagSize+1, 0));
	// 初始化dp
	for (int i = 0; i < coins.size(); ++i) dp[i][0] = 1;
	// 可以兑换 +1 方法
	for (int j = 0; j <= bagSize; ++j) if (j % coins[0] == 0) dp[0][j] = 1;
	// 遍历dp
	for (int i = 1; i < coins.size(); ++i) {
		for (int j = 0; j  <= bagSize; ++j) {
			if (coins[i] > j) dp[i][j] = dp[i-1][j];
			else dp[i][j] = dp[i-1][j] + dp[i][j - coins[i]];
		}
	}
	return dp[coins.size()-1][bagSize];
}

377. 组合总和 Ⅳ - 力扣(LeetCode)

完全背包的求排列问题,在上一题基础上变换遍历顺序即可

  1. Dp 数组表示当前装满 j 背包多少种方法

  2. 递推公式基于二维递推公式得出 dp[j]+=dp[j-nums[i]] i 表示物品 j 表示背包

  3. 初始化 dp[0]=1

  4. 遍历顺序先遍历背包再遍历物品求排列,先遍历物品再遍历背包求组合

  5. 打印 dp

cpp 复制代码
int combinationSum4(vector<int>& nums, int target) {
	// dp
	std::vector<int> dp(target+1, 0);
	// 初始化
	dp[0] = 1;
	// dp遍历
	for (int j = 0; j <= target; ++j) {
		for (int i = 0; i < nums.size(); ++i) {
			if (j - nums[i] >= 0 && dp[j] <= INT_MAX - dp[j - nums[i]]) dp[j] += dp[j - nums[i]];
		}
	}
	return dp[target];
}

57. 爬楼梯(第八期模拟笔试)

爬楼梯进阶版,使用 dp 数组实现,求方法排列组合 121 和 211 两种方法

背包是 n 级台阶,物品是 m 上台阶方法,从 1 开始遍历因为题目要求

  1. Dp 数组表示第 j 容量(楼梯)有多少种方法

  2. 递推公式如上题,从之前的数据中累加的来 dp[j] += dp[j-nums[i]]

  3. Dp 初始化 dp[0]=1

  4. 遍历顺序先遍历背包再遍历物品

  5. Dp 打印

cpp 复制代码
#include<iostream>
#include<vector>

int main() {
    int m = 0, n = 0;
    std::cin >> n >> m;

    // 定义dp
    std::vector<int> dp(n+1, 0);
    dp[0] = 1;
    // 遍历dp 先遍历背包n,再遍历物品m
    for (int j = 1; j <= n; ++j) {
        for (int i = 1; i <= m; ++i) {
            // 背包有空间的情况下
            if (j - i >= 0) dp[j] += dp[j - i];
        }
    }

    std::cout << dp[n] << std::endl;
    return 0;
}
相关推荐
不正经学生14 小时前
C语言大小端字节序:内存里字节的排列顺序
c语言·开发语言·arm开发·c++·算法·c#
大模型探索者14 小时前
2026金融大模型训推平台选型指南:主流厂商横向对比与私有化落地
人工智能·算法·金融
依然鸣15 小时前
PTA团体程序设计天梯赛L2真题讲解L2-001-004
经验分享·学习·算法·深度优先·pat考试
杨航 AI17 小时前
** AI 面试算法 50 题清单**,不是单纯的 LeetCode 题号列表,而是按照“**考察概率 × 面试价值 × 你当前准备方向**”排序
算法·leetcode·面试
m0_720245011 天前
1543.统计好三元组(简单)
开发语言·算法
To_OC1 天前
LC 560 和为 K 的子数组:前缀和配哈希表,这对组合我是真的服了
javascript·算法·程序员
hans汉斯1 天前
《软件工程与应用》期刊推荐&10月版面征稿中
图像处理·人工智能·深度学习·算法·音视频·软件工程
叠层归一研究院1 天前
AGI 系统(八):符号范畴嵌入函子 — SymCat ↪ C_M107 严格化
c语言·开发语言·人工智能·算法·transformer·agi
其美杰布-富贵-李1 天前
08 进阶评估指标与算法特定指标
人工智能·算法
.道阻且长.1 天前
5.LeetCode算法习题讲解--双指针--有效三角形的个数
算法·leetcode·职场和发展