寻找数字的最佳可能子集组合以达到给定的总和或最接近给定的总和

所以,我有这个问题需要解决,显然这被称为Subset Sum Problem,除了我不仅需要在精确到给定数字时获得子集,而且在没有精确和达到给定数字的情况下最接近数字,它不应该超过参考数字,只在下面,如果有两个以上可能的子集具有相同的结果,我想得到分布更好的子集,从最高到最低的数字数组作为首选,并限制每个子集不超过相同数量的 10 次,允许重复,例如:

这是具有预定义值的数组:

let num = [64.20, 107, 535, 1070];

和一个给定的数字:

let investment = 806.45

一种可能的解决方案是:

[0, 2, 1, 0] // this sums up to 749 (since there is no way to get to 806.45 with the given array)

请注意,此结果是指 nums 中的每个值允许达到总和的次数:

但更好的解决方案是:

[4, 5, 0, 0] // this sums up to 791.80 (since there is no way to get to 806.45 with the given array)

还有一个更好的解决方案(因为首先考虑较高的值而不是较低的值)

[4, 0, 1, 0] // this sums up to 791.80 also but you can see it's taking a higher value when possible.

另一个重要的限制是永远不应该给出负面结果。

到目前为止,我已经尝试过这样(在 VueJS 中):

getPackages(){
      let investment = 806.45;
      const num = [64.20, 107, 535, 1070]
      let a, b, c, d;
      let results = [];

      a = investment / num[0] >= 0 ? (investment/num[0]) : 0;
      b = investment / num[1] >= 0 ? (investment/num[1]) : 0;
      c = investment / num[2] >= 0 ? (investment/num[2]) : 0;
      d = investment / num[3] >= 0 ? (investment/num[3]) : 0;

      let dResult = [], cResult = [], bResult = [], aResult = [];

      for (let i = 0; i <= d; i++){
        if (i>0){
          dResult.push((i * num[3]))
        }
      }

      for (let i = 0; i <= c; i++){
        if (i>0){
          cResult.push((i * num[2]))
        }
      }

      for (let i = 0; i <= b; i++){
        if (i>0){
          bResult.push((i * num[1]))
        }
      }

      for (let i = 0; i <= a; i++){
        if (i>0){
          aResult.push((i * num[0]))
        }
      }

      let aResultCoincidences = [];
      let bResultCoincidences = [];
      let cResultCoincidences = [];
      let dResultCoincidences = [];

      bResult.forEach(value => {
        aResult.findIndex(item => item === value) > 0 ? bResultCoincidences.push(aResult.findIndex(item => item === value)) : null
      })

      aResult.splice(0, Math.max(...bResultCoincidences) + 1)

      cResult.forEach(value => {
        bResult.findIndex(item => item === value) > 0 ? cResultCoincidences.push(bResult.findIndex(item => item === value)) : null
      })

      bResult.splice(0, Math.max(...cResultCoincidences) + 1)

      dResult.forEach(value => {
        cResult.findIndex(item => item === value) > 0 ? dResultCoincidences.push(cResult.findIndex(item => item === value)) : null
      })

      cResult.splice(0, Math.max(...dResultCoincidences) + 1)

      this.package1 = aResult.length
      this.package2 = bResult.length
      this.package3 = cResult.length
      this.package4 = dResult.length

    },

在我的方法中发生的事情是,我尝试从每次乘法中获得所有可能的结果,然后我删除我用这种组合制作的数组之间匹配的那些,最终得到结果,但这没有得到很好的优化,我肯定有可能有更好的解决方案来解决这个问题。

无论如何忽略 vuejs 实现,这只是在 DOM 中设置值。

*** ES6 解决方案会很棒。

可以玩的CodeSandbox:CODESANDBOX LINK

提前致谢。

以上是寻找数字的最佳可能子集组合以达到给定的总和或最接近给定的总和的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>