Questo è un programma binario relativamente semplice.
Suggerisco forza bruta con la potatura. Se in qualsiasi momento si supera il peso consentito, non è necessario provare combinazioni di elementi aggiuntivi, è possibile scartare l'intero albero.
Oh aspetta, hai negativo pesi? Includere sempre tutti i pesi negativi, quindi procedere come sopra per i pesi positivi. Oppure gli articoli con peso negativo hanno anche un valore negativo?
Includere tutte le voci di peso negativo con valore positivo. Escludere tutti gli articoli con peso positivo e valore negativo.
Per le voci di peso negativo con valore negativo, sottrarre il loro peso (aumentando la capavità dello zaino) e utilizzare uno pseudo-articolo che rappresenta non prendendo quell'elemento. Lo pseudo articolo avrà un peso e un valore positivi. Procedi con la forza bruta con la potatura.
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;
}
}
fonte
2011-11-14 17:20:19
Forse intendevi veramente * * risolvibili, o * risolvibile in modo efficiente *? –
Se non hai bisogno di una risposta esatta, potresti esaminare la ricottura simulata .. –
2^10 è 1024. Definitivamente forza bruta, anche se c'è un modo "migliore" sarà quasi certamente molto più lento. –