获得具有个别成本和限制的最大可负担物品数量的算法

Algorithm to get maximum affordable amount of items with individual costs and limits

关于在具有不同成本和限制的 n 个项目之间均匀分配固定数量点的有效方法的问题,我有点头疼。每个项目的成本不会增加。

假设我有 3 个项目:

Name Cost Limit
A 25 220
B 30 20
C 50 60

此外,我们还获得了固定积分:5000。 我想知道我可以购买多少次。 我当前的解决方案运行一个循环并从点数中扣除成本,直到达到所有限制或点数 运行。 http://jsfiddle.net/nasc8rfL/



var points = 5000;
var costA = 25;
var costB = 30;
...

var limitA = 220;
...

var maxA = 0;

while (points > 0){
   if (points >= costA && limitA > 0){
     points -=costA;
     limitA -=1;
     maxA +=1;
   };
   if (points >= costB && limitB > 0){
     points -=costB;
     limitB -=1;
     maxB +=1;
   };
   if (points >= costC && limitC > 0){
     points -=costC;
     limitC -=1;
     maxC +=1;
   };
   if((points < costA) and (points < costB) and (points <costC)) break; 
}    

console.log(maxA,maxB,maxC);


最终它不会停留在 A、B、C,而是可变数量的元素(不超过 20 个)所以我会遍历每个元素而不是 3 个 IF。

我其实不用扣分,我只需要知道每件商品能买多少。我觉得我遗漏了什么,有一种更简单的方法来确定每一个的数量。

我曾考虑过根据它们的极限对它们进行加权,但我的头脑不想和我一起工作,我现在很困。

此外,我是 javascript 的初学者,所以如果你们有一些技巧可以使显示的循环更快或更方便,也许可以使用

function func(arr){
  arr.forEach(x=>{doSomething();})

我会非常高兴。

你的方法不错。该算法可以通过

加快一点
  • 将元素保留在一个列表中,而不只是在外循环的每次迭代中访问每个元素,而是在达到限制后将其踢出列表
  • 不仅每轮每件都买一件,而且如果你在预算范围内每件都买同样多的话,尽可能多买。

const points = 5000;
const items = [
  {name: "A", cost: 25, limit: 220},
  {name: "B", cost: 30, limit: 60},
  {name: "C", cost: 50, limit: 20},
];
let amounts = Object.fromEntries(items.map(i => [i.name, 0]));
let available = items;
let toSpend = points;
do {
  available = available.filter(i => amounts[i.name] < i.limit && i.cost <= toSpend);
  const maxAmount = Math.max(1, Math.floor(toSpend / available.reduce((s, i) => s+i.cost, 0)));
  for (const a of available) {
    const amount = Math.min(maxAmount, a.limit - amounts[a.name]);
    if (amount * a.cost <= toSpend) {
      amounts[a.name] += amount;
      toSpend -= amount * a.cost;
    } else {
      break;
    }
  }
} while (available.length);
console.log(amounts);
console.log(`Leftover: ${toSpend}`);