【C++动态规划 多重背包】1774. 最接近目标价格的甜点成本|1701

本文涉及知识点

C++动态规划
C++背包问题

LeetCode 1774. 最接近目标价格的甜点成本

你打算做甜点,现在需要购买配料。目前共有 n 种冰激凌基料和 m 种配料可供选购。而制作甜点需要遵循以下几条规则:

必须选择 一种 冰激凌基料。

可以添加 一种或多种 配料,也可以不添加任何配料。

每种类型的配料 最多两份 。

给你以下三个输入:

baseCosts ,一个长度为 n 的整数数组,其中每个 baseCostsi 表示第 i 种冰激凌基料的价格。

toppingCosts,一个长度为 m 的整数数组,其中每个 toppingCostsi 表示 一份 第 i 种冰激凌配料的价格。

target ,一个整数,表示你制作甜点的目标价格。

你希望自己做的甜点总成本尽可能接近目标价格 target 。

返回最接近 target 的甜点成本。如果有多种方案,返回 成本相对较低 的一种。

示例 1:

输入:baseCosts = 1,7, toppingCosts = 3,4, target = 10

输出:10

解释:考虑下面的方案组合(所有下标均从 0 开始):

  • 选择 1 号基料:成本 7
  • 选择 1 份 0 号配料:成本 1 x 3 = 3
  • 选择 0 份 1 号配料:成本 0 x 4 = 0
    总成本:7 + 3 + 0 = 10 。
    示例 2:

输入:baseCosts = 2,3, toppingCosts = 4,5,100, target = 18

输出:17

解释:考虑下面的方案组合(所有下标均从 0 开始):

  • 选择 1 号基料:成本 3
  • 选择 1 份 0 号配料:成本 1 x 4 = 4
  • 选择 2 份 1 号配料:成本 2 x 5 = 10
  • 选择 0 份 2 号配料:成本 0 x 100 = 0
    总成本:3 + 4 + 10 + 0 = 17 。不存在总成本为 18 的甜点制作方案。
    示例 3:

输入:baseCosts = 3,10, toppingCosts = 2,5, target = 9

输出:8

解释:可以制作总成本为 8 和 10 的甜点。返回 8 ,因为这是成本更低的方案。

示例 4:

输入:baseCosts = 10, toppingCosts = 1, target = 1

输出:10

解释:注意,你可以选择不添加任何配料,但你必须选择一种基料。

提示:

n == baseCosts.length

m == toppingCosts.length

1 <= n, m <= 10

1 <= baseCostsi, toppingCostsi <= 104

1 <= target <= 104

动态规划 多重背包

动态规划的状态表示

价格最低的基料价格为m1,如果m1大于target,则只选择此基料。否则需要考虑的最大价格为M= target+m1。

dpim 表示选择了一种基料,和前m种辅料后,辅料可能0到2份,能否价格为m。

动态规划的转移方程

枚举前置状态

dpi+1 = dpi 不选择辅料

dpi+1m+tc\[i] ||= dpim 选择一份辅料

dpi+1m+tc\[i*2] ||= dpim 选择两份辅料

动态规划的初始值

如果存在价格x的基料,则dp0x=true,其它全部为false。

动态规划的填报顺序

i = 0 to n-1 m = 0 to M-tci

动态规划的返回值

dp.back()x成立, min(abs(x-target)) 从小到大枚举x。

代码

核心代码

cpp 复制代码
class Solution {
		public:
			int closestCost(vector<int>& baseCosts, vector<int>& toppingCosts, int target) {
				const int iMin = *min_element(baseCosts.begin(), baseCosts.end());
				if (iMin >= target)return iMin;
				const int M = target + (target-iMin);
				vector<bool> pre(M + 1);
				auto Add = [&](vector<bool>& dp,int cur) {
					if (cur > M)return;
					dp[cur] = true;
				};
				for (const auto& n : baseCosts) {
					Add(pre, n);
				}
				for (const auto& n : toppingCosts) {
					vector<bool> dp = pre;
					for (int i = 0; i <= M; i++) {
						if (!pre[i])continue;
						Add(dp, i + n);
						Add(dp, i + n*2);
					}
					pre.swap(dp);
				}
				for (int i = 0; i <= target; i++) {
					if (pre[target - i]) { return  target - i; }
					if (pre[target + i]) { return  target + i; }
				}
				return -1;
			}
		};

单元测试

cpp 复制代码
vector<int> baseCosts, toppingCosts;
		int target;
		TEST_METHOD(TestMethod11)
		{
			baseCosts = { 1,7 }, toppingCosts = { 3,4 }, target = 10;
			auto res = Solution().closestCost(baseCosts, toppingCosts, target);
			AssertEx(10, res);
		}
		TEST_METHOD(TestMethod12)
		{
			baseCosts = { 2,3 }, toppingCosts = { 4,5,100 }, target = 18;
			auto res = Solution().closestCost(baseCosts, toppingCosts, target);
			AssertEx(17, res);
		}
		TEST_METHOD(TestMethod13)
		{
			baseCosts = { 3,10 }, toppingCosts = { 2,5 }, target = 9;
			auto res = Solution().closestCost(baseCosts, toppingCosts, target);
			AssertEx(8, res);
		}
		TEST_METHOD(TestMethod14)
		{
			baseCosts = { 10 }, toppingCosts = { 1 }, target = 1;
			auto res = Solution().closestCost(baseCosts, toppingCosts, target);
			AssertEx(10, res);
		}

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17

如无特殊说明,本算法用**C++**实现。

相关推荐
得物技术9 分钟前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六3 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术4 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize5 小时前
初识DFS 与 BFS:递归、队列与图遍历
算法
罗西的思考18 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl