查找可重复以适应最大总值的值集的算法

Algorithm to find the set of values which are repeatable to fit upto a maximum Total value

我有一套价值观。 (它的长度可以是动态的。一些值可以是未定义的)。这些值中的每一个都是一种攻击类型。

例如:attacks=[960,1200,1800,2120,undefined,undefined];

还有一个总值,

例如:totalEnergy=18680;

现在我想要一个函数来 return 对象数组,例如

例如:

[{
    attacks: [0,0,0,0,1,2],
    wastage: 128
    }, {
    attacks: [0,1,2,2,2],
    wastage: 298
    }, {
    attacks: [2,3,4],
    wastage: 593
}]

所以这里的攻击是可能的攻击组合,可以在给定的能量限制和剩余的能量浪费量内完成。 因此该函数将有一个名为 wastage 的参数,该参数将提及可以完成的最大浪费量。 各种类型的攻击可以重复多次。但是消耗的总能量应该小于总能量。

理想情况下,更高级别的攻击次数是首选,就像花费更多的攻击一样,但这取决于玩家的决定。所以我会 return 所有可能的组合。玩家必须选择性价比最高的。

我知道这是某种背包问题,但我尝试了多种解决方案,但没有一个能完全解决这个问题。

我通常希望此解决方案在 javascript 中,但任何语言都可以用于演示目的。

更新:

这是我目前得到的,

let totalEnergy = 3400;
let attacks = [980, 1220, 1680, 1920];
let attacksPossible = attacks.map((attack, iter) => {
    return Math.floor(totalEnergy/attack);
})
// Create an array which contains a repeatitive number of attacks possible
let attacksArray = attacks.map((attack, iter) => {
    return [...Array(attacksPossible[iter])].map(() => attack)
})
// Flatten 2D array into 1D array
attacksArray = [].concat.apply([], attacksArray);

console.log('attacksPossible', attacksPossible);
console.log('attacksArray', attacksArray);

这里我得到了一个数组列表,其中包含给定总值的最大攻击组合,现在我该如何从这里开始实施背包?

背包在这里并不重要,因为您需要所有选择。这更类似于将一组数字划分为总和 n 的所有方法,除了您可能会浪费。方法相同,稍作修改:

let totalEnergy = 3400;
let attacks = [980, 1220, 1680, 1920];

let possibilities = [];
let current = [];

let minVal = Math.min.apply(null, attacks);
function solve (idx, left) {
  for (var i = idx; i < attacks.length;i++) {
    if (attacks[i] != undefined && attacks[i] <= left) {
      current.push(i);
      solve(i, left - attacks[i]);
      current.pop();
    }
  }
  
  if (left < minVal) {
    possibilities.push({attacks: current.slice(0), waste: left})
  } 
}

solve(0, totalEnergy);
console.log(possibilities);