V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
tmsdy0404
V2EX  ›  问与答

求助,一个比多重背包还要复杂一点的问题。

  •  
  •   tmsdy0404 · 2022-03-19 11:41:09 +08:00 · 866 次点击
    这是一个创建于 770 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现有商品 N(N<100)类,第 i 类商品的数量为 C[i],单价为 P[i], 即第 i 类商品的总价格为 C[i]*P[i]。 则所有商品的总价格 PN 为:

    商品总价格

    另有发票 M(M<N)张。 第 k 张发票的金额为 V[k]。 所以发票的总金额 PM 为:

    发票总金额

    且 PM = PN 。

    求如何分配商品,使其总金额刚好对应上每一张发票金额。 (允许有正负 1 元的误差,我也觉得不可理解,但事实就是这样)

    ^^^^^^^^^^^^^^说人话的分割线^^^^^^^^^^^^^^^^^^^^^^^

    上面说的可能不太清楚,我直接举例: 样例

    绿色区域就是要求解的值。可能有很多解,只需要求出来使每个发票金额刚好满足就可以。

    个人感觉,如果把每一张发票金额去按多重背包问题求最优,不一定能保证所有发票整体最优。 另外,我这个价格也就是背包问题中的体积,是有小数的,难道要全部放大 100 倍来求解吗?

    tmsdy0404
        1
    tmsdy0404  
    OP
       2022-03-19 12:55:35 +08:00 via iPhone
    坐等大佬解惑~~~~
    wa007
        2
    wa007  
       2022-03-19 19:10:35 +08:00
    相比多重背包,你这个题目一共有 M 个背包,套用多重背包的做法开销实在太大了。
    这应该是个业务问题,不是个算法问题吧。
    wa007
        3
    wa007  
       2022-03-19 19:27:55 +08:00
    1. 初始化
    1 )把所有商品放入集合 A
    2 )把所有发票放入集合 B

    2. 迭代
    1 )调用多重背包算法,判断当前的集合 A 都可以组成和为哪些金额的发票,输出数组 A_array ,A_array[i] = True 表示 金额为 i 的发票可以由集合 A 中的某些商品求和得到,A_array[j] = False 表示金额 j 的发票不能由 A 中的商品求和得到。
    2 )从小到大遍历集合 B 中的发票,假设当前是金额为 i 的发票,判断 A_array[i] 如果是 True ,就把 i 从集合 B 中删除,同时加入 {j - i for j in B if j > i}(因为你下次可以组成金额为 j-i 的发票,然后把 j 删除,i 再放回 B ),再把 A 中对应的商品剔除。如果 A_array[i] = False ,就继续遍历。如果 B 中全都是 False ,就结束。PS:如果你抽到了 j-i ,就要把 j 删除,加入 i ,对每个发票打个标记,表示如果删除当前发票,需要加入哪些发票。
    3 )直到 A 或者 B 为空,或 B 中找不到满足条件的发票为止。

    时间复杂度就不算了,随机数据的耗时肯定是大大小于最差复杂度的。如果数据量不大,应该是可行的。
    tmsdy0404
        4
    tmsdy0404  
    OP
       2022-03-19 19:55:27 +08:00
    @wa007 量有点大啊,没办法把集合 A 的所有组合全部弄出来。
    这是实际的数据,虽然商品各类不多,但有的商品数量是 40000 个,
    单这个商品就有 2 的 40000 次方-1 种组合,这个量级没法弄吧


    ![quicker_9f6f1ecd-2481-4cfe-8ab7-855eabf3ee7f.png]( https://s2.loli.net/2022/03/19/BvxKHk78uziVUm9.png)
    wa007
        5
    wa007  
       2022-03-19 20:10:40 +08:00
    你看下背包算法,实现第一步不需要「 2 的 40000 次方-1 种组合」,复杂度主要跟 `PN` 有关
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2512 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 00:23 · PVG 08:23 · LAX 17:23 · JFK 20:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.