如何用Python解决带数量限制的n家商店硬币选取最大化问题?
嘿,这是个典型的带多重约束的0-1选择优化问题,用动态规划(DP)就能高效解决。我来一步步拆解,从问题分析到解法思路,再结合你的示例详细说明:
问题清晰化
先把核心规则再理一遍,避免歧义:
- 有
n家商店,每家店提供3种硬币(GOLD、PLATINUM、DIAMOND),每家店最多选其中一种硬币(选的话必须拿该店对应硬币的全部数量,最优解里不会跳过任何一家,因为选了肯定能提升总数量) - 三种硬币分别有获取上限:GOLD最多选
g_max家店的、PLATINUM最多p_max家、DIAMOND最多d_max家(示例里的上限2/1/1,刚好对应最优策略选2家GOLD、1家PLATINUM、1家DIAMOND) - 目标是让拿到的硬币总数量尽可能大
动态规划解法思路
我们可以用三维DP数组来记录状态,逻辑非常直观:
- 状态定义:
dp[g][p][d]表示已经选了g家店的GOLD、p家店的PLATINUM、d家店的DIAMOND时,能拿到的最大硬币总数。 - 初始状态:
dp[0][0][0] = 0(啥都没选的时候总和为0),其他状态初始为0或者负无穷(表示这个状态暂时不可达)。 - 状态转移:遍历每家商店的三个硬币数量
(g_i, p_i, d_i),然后对所有当前可达的(g,p,d)状态,分别尝试选这家店的三种硬币:- 如果选GOLD:只要
g + 1 <= g_max,就更新dp[g+1][p][d] = max(dp[g+1][p][d], dp[g][p][d] + g_i) - 如果选PLATINUM:只要
p + 1 <= p_max,就更新dp[g][p+1][d] = max(dp[g][p+1][d], dp[g][p][d] + p_i) - 如果选DIAMOND:只要
d + 1 <= d_max,就更新dp[g][p][d+1] = max(dp[g][p][d+1], dp[g][p][d] + d_i)
- 如果选GOLD:只要
- 最终结果:遍历所有
0<=g<=g_max、0<=p<=p_max、0<=d<=d_max的dp[g][p][d],取最大的那个值就是答案。
示例一步步验证
咱们拿你给的示例走一遍,确保思路正确:
输入回顾
4(商店数量)
2 1 1(GOLD最多选2家,PLATINUM最多1家,DIAMOND最多1家)
商店1:5 4 5(GOLD5枚,PLATINUM4枚,DIAMOND5枚)
商店2:4 3 2
商店3:10 9 7
商店4:8 2 9
状态转移关键步骤
- 处理商店1:
- 选GOLD:
dp[1][0][0] = 5 - 选PLATINUM:
dp[0][1][0] = 4 - 选DIAMOND:
dp[0][0][1] =5
- 选GOLD:
- 处理商店2:
- 从
dp[1][0][0]出发:选GOLD到dp[2][0][0] =5+4=9;选PLATINUM到dp[1][1][0] =5+3=8 - 从
dp[0][1][0]出发:选GOLD到dp[1][1][0](和之前的8持平,无需更新);选DIAMOND到dp[0][1][1] =4+2=6 - 从
dp[0][0][1]出发:选GOLD到dp[1][0][1] =5+4=9;选PLATINUM到dp[0][1][1]更新为max(6,5+3=8)
- 从
- 处理商店3:
- 从
dp[2][0][0]出发:选PLATINUM到dp[2][1][0] =9+9=18;选DIAMOND到dp[2][0][1] =9+7=16 - 从
dp[1][1][0]出发:选GOLD到dp[2][1][0](和18持平);选DIAMOND到dp[1][1][1] =8+7=15 - 从
dp[0][1][1]出发:选GOLD到dp[1][1][1]更新为max(15,8+10=18)
- 从
- 处理商店4:
- 从
dp[2][1][0]出发:只能选DIAMOND(GOLD和PLATINUM的名额已用完),dp[2][1][1] =18+9=27 - 从
dp[1][1][1]出发:选GOLD到dp[2][1][1]是18+8=26,比27小,所以最终最大值是27
- 从
这个结果刚好对应示例里的最优策略:商店1、3选GOLD(5+10=15),商店2选PLATINUM(3),商店4选DIAMOND(9),总和15+3+9=27。
优化小技巧
如果商店数量n很大,或者三种硬币的上限数值比较高,三维DP的空间可能有点吃紧。这时候可以用滚动数组优化:因为每次处理新商店只需要上一轮的状态,所以我们可以用两个三维数组(当前轮和上一轮)来交替更新,把空间从O(g_max*p_max*d_max)降到一半。如果上限数值特别大,还可以考虑按维度压缩空间,但对于大多数题目规模,基础的三维DP已经足够高效了。
内容的提问来源于stack exchange,提问作者Hemant Chauhan
相关产品推荐
相关产品推荐

