青训营X豆包MarsCode 技术训练营笔记3| 豆包MarsCode AI 刷题

35 阅读7分钟

小F的超市购物策略

问题描述

小F正在超市购物,有nn个商品摆成一排,每个商品的价格为aiai​,小F对它的喜爱度为bibi​。所有商品的价格都是偶数。超市有一个活动:当小F以原价购买某件商品时,她可以用半价购买下一件右边相邻的商品(当然也可以选择以原价购买,这样下一件商品仍有机会半价购买)。然而,如果小F半价购买了一件商品,那么下一件相邻的商品只能原价购买。

小F手中有xx金额,她希望通过购物活动,尽可能最大化她获得的喜爱度总和,并且购买的商品总价格不能超过她的初始金额xx。

思路分析

  1. 问题理解 本题描述了小F在超市购物的场景,有一系列商品,每个商品有价格和小F对其的喜爱度,并且存在特定的购买优惠活动规则。目标是在给定的初始金额限制下,通过合理选择购买商品的方式(利用半价购买的优惠活动),最大化小F获得的喜爱度总和。 #### 2. 算法思路 - 深度优先搜索(DFS)
  • 状态表示: - 在代码中,通过 dfs 函数的参数来表示不同的状态。i 表示当前考虑购买的商品索引,从 0 开始逐步遍历到 n - 1n 是商品总数)。 - t 表示当前已经花费的总金额,用于和初始金额 x 进行比较,以确保不超过预算。 - love 表示到当前商品为止已经获得的喜爱度总和,通过不断更新这个值来尝试找到最大的喜爱度总和。 - half 是一个关键的状态标识,用于表示上一件商品是否是以半价购买的。如果 half1,则意味着上一件商品是半价购买的,那么当前商品只能原价购买;如果 half0,则当前商品有两种选择:原价购买或者利用半价优惠购买下一件商品(如果购买当前商品的话)。
  • 搜索过程: - 首先,在 dfs 函数中,判断当前是否已经遍历完所有商品(i == n)或者已经超过了初始金额(t > x)。如果是这样的情况,需要进行一些处理来判断当前的喜爱度总和是否是最大的。如果 t > x,说明已经超支了,此时需要减去最后考虑购买的商品的喜爱度和价格(因为这种情况不符合要求),然后再与当前记录的最大喜爱度 maxlove 进行比较,如果当前的 love 更大,则更新 maxlove。 - 接下来,根据 half 的值进行不同的分支搜索: - 如果 half1,即上一件商品是半价购买的,那么当前商品只能原价购买。所以调用 dfs 函数,将商品索引 i 增加 1,花费金额 t 增加当前商品价格 a[i] 的一半(因为只能原价购买),喜爱度 love 增加当前商品的喜爱度 b[i],并且将 half 设置为 0(因为下一件商品又有了原价购买或半价购买的选择),继续进行深度优先搜索。 - 如果 half0,此时当前商品有两种选择: - 第一种选择是原价购买当前商品并且可以半价购买下一件商品(如果购买下一件商品的话)。调用 dfs 函数,将商品索引 i 增加 1,花费金额 t 增加当前商品价格 a[i],喜爱度 love 增加当前商品的喜爱度 b[i],并且将 half 设置为 1(表示下一件商品只能原价购买了,如果购买的话),继续深度优先搜索。 - 第二种选择是原价购买当前商品,但下一件商品也保持原价购买的可能性(即不利用半价购买下一件商品的优惠)。调用 dfs 函数,将商品索引 i 增加 1,花费金额 t 增加当前商品价格 a[i],喜爱度 love 增加当前商品的喜爱度 b[i],并且将 half 设置为 0,继续深度优先搜索。 - 最后,还有一种情况是不购买当前商品,直接考虑下一件商品。调用 dfs 函数,将商品索引 i 增加 1,花费金额 t 和喜爱度 love 保持不变,并且将 half 设置为 0,继续深度优先搜索。 通过这样全面的深度优先搜索,遍历所有可能的购买商品的组合方式,最终找到在不超过初始金额的情况下,能够获得最大喜爱度总和的购买方案。

代码分析

1. 头文件引入

代码开头引入了一系列标准库头文件,如 <iostream> 用于输入输出操作,<cstdio><cmath><cstdlib><cstring> 等提供了各种基础的函数和数据类型操作功能,<algorithm> 用于一些算法相关的操作(如排序等,虽然本题未直接用到排序,但可能是为了通用性引入),<iomanip> 用于格式化输出操作,<queue><stack><vector><set><map> 分别用于实现队列、栈、向量、集合、映射等数据结构,<functional> 可能用于一些函数对象相关的操作(在本题中可能未直接体现其作用)。这些头文件的引入为后续代码实现提供了丰富的工具和数据结构支持。

2. 全局变量定义

定义了一个全局变量 maxlove 并初始化为 0,用于记录在所有可能的购买方案中能够获得的最大喜爱度总和。在每次调用 solution 函数开始时,会先将 maxlove 重置为 0,然后通过 dfs 函数的搜索过程不断更新这个值,直到找到最大的喜爱度总和。

3. dfs 函数分析
  • 参数含义: - i:当前考虑购买的商品索引。 - t:当前已经花费的总金额。 - love:到当前商品为止已经获得的喜爱度总和。 - half:表示上一件商品是否是以半价购买的,1 表示是,0 表示否。 - n:商品的总数。 - x:小F手中的初始金额。 - a:存储各个商品价格的向量。 - t:存储各个商品喜爱度的向量。
  • 函数主体逻辑: - 首先判断 i == n 或者 t > x 的情况,如前面思路分析所述,处理超支情况并更新 maxlove。 - 然后根据 half 的值进行不同的分支调用 dfs 函数,实现深度优先搜索的不同路径探索,每种路径对应一种可能的购买商品的决策方式,通过不断递归调用 dfs 函数,遍历所有可能的购买组合,找到最大喜爱度总和的方案。
4. solution 函数分析
  • 函数接受 n(商品总数)、x(初始金额)、a(商品价格向量)、b(商品喜爱度向量)作为参数。 - 在函数内部,首先将 maxlove 重置为 0,然后调用 dfs 函数从初始状态(i = 0t = 0love = 0half = 0)开始进行深度优先搜索,最终返回找到的最大喜爱度总和 maxlove
5. main 函数分析
  • main 函数中,通过调用 solution 函数并与预期的结果进行比较,来验证 solution 函数的正确性。分别对三组不同的输入数据(商品数量、初始金额、商品价格向量、商品喜爱度向量)进行测试,输出比较结果(truefalse),以检查代码是否能正确计算出在不同输入情况下的最大喜爱度总和。例如,对于输入 (4, 7, {2, 2, 6, 2}, {3, 4, 5, 1}),期望得到的最大喜爱度总和是 12,通过调用 solution 函数计算并与 12 进行比较,输出比较结果。同样地,对另外两组输入数据也进行类似的测试操作。