You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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数组来记录状态,逻辑非常直观:

  1. 状态定义:dp[g][p][d]表示已经选了g家店的GOLD、p家店的PLATINUM、d家店的DIAMOND时,能拿到的最大硬币总数。
  2. 初始状态:dp[0][0][0] = 0(啥都没选的时候总和为0),其他状态初始为0或者负无穷(表示这个状态暂时不可达)。
  3. 状态转移:遍历每家商店的三个硬币数量(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)
  4. 最终结果:遍历所有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. 处理商店1:
    • 选GOLD:dp[1][0][0] = 5
    • 选PLATINUM:dp[0][1][0] = 4
    • 选DIAMOND:dp[0][0][1] =5
  2. 处理商店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. 处理商店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. 处理商店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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:54:02