Это относительно простая двоичная программа.
Я бы предложил грубую силу с обрезкой. Если в любой момент вы превысите допустимый вес, вам не нужно пробовать комбинации дополнительных предметов, вы можете отказаться от всего дерева.
Ой, подождите, у вас есть отрицательные веса? Всегда включайте все отрицательные веса, затем действуйте как указано выше для положительных весов. Или предметы с отрицательным весом также имеют отрицательное значение?
Включите все элементы с отрицательным весом с положительным значением. Исключить все элементы с положительным весом и отрицательным значением.
Для предметов с отрицательным весом, имеющих отрицательное значение, вычтите их вес (увеличивая емкость рюкзака) и используйте псевдоэлемент, который представляет , а не взятие этого предмета. Псевдоэлемент будет иметь положительный вес и ценность. Продолжить грубой силой с обрезкой.
class Knapsack
{
double bestValue;
bool[] bestItems;
double[] itemValues;
double[] itemWeights;
double weightLimit;
void SolveRecursive( bool[] chosen, int depth, double currentWeight, double currentValue, double remainingValue )
{
if (currentWeight > weightLimit) return;
if (currentValue + remainingValue < bestValue) return;
if (depth == chosen.Length) {
bestValue = currentValue;
System.Array.Copy(chosen, bestItems, chosen.Length);
return;
}
remainingValue -= itemValues[depth];
chosen[depth] = false;
SolveRecursive(chosen, depth+1, currentWeight, currentValue, remainingValue);
chosen[depth] = true;
currentWeight += itemWeights[depth];
currentValue += itemValues[depth];
SolveRecursive(chosen, depth+1, currentWeight, currentValue, remainingValue);
}
public bool[] Solve()
{
var chosen = new bool[itemWeights.Length];
bestItems = new bool[itemWeights.Length];
bestValue = 0.0;
double totalValue = 0.0;
foreach (var v in itemValues) totalValue += v;
SolveRecursive(chosen, 0, 0.0, 0.0, totalValue);
return bestItems;
}
}