Felix ist richtig, dass dies ein Sonderfall des Rucksackproblems ist. Sein dynamischer Programmieralgorithmus nimmt die Größe der Zeit und die Größe (K * M) Größe und O (K * K * M). Ich glaube, dass seine Verwendung der Variablen N wirklich sein sollte K.
Es gibt zwei Bücher, die dem Rucksackproblem gewidmet sind. Der letzte von Kellerer, Pferschy und Pisinger [2004, Springer-Verlag, ISBN 3-540-40286-1] gibt einen verbesserten dynamischen Programmieralgorithmus auf ihrer Seite 76, Abbildung 4.2, die den Raum (K + M) einnimmt und O (KM) Zeit, was eine enorme Reduzierung im Vergleich zu dem von Felix gegebenen dynamischen Programmieralgorithmus ist. Beachten Sie, dass es in der letzten Zeile des Algorithmus einen Tippfehler gibt, wo es c-bar sein sollte: = c-bar - w_ (r (c-bar)).
Meine C# Implementierung ist unten. Ich kann nicht sagen, dass ich es ausführlich getestet habe, und ich begrüße das Feedback dazu. Ich habe verwendet, um das Konzept der Mengen zu implementieren, die in dem Algorithmus in dem Buch angegeben sind. In meinem Code c
ist die Kapazität (die in der ursprünglichen Post M genannt wurde), und ich w
anstelle von A
als das Array, das die Gewichte enthält.
Ein Beispiel für seine Verwendung ist:
int[] optimal_indexes_for_ssp = new SubsetSumProblem(12, new List<int> { 1, 3, 5, 6 }).SolveSubsetSumProblem();
wo das Array optimal_indexes_for_ssp
enthält [0,2,3] entsprechend den Elementen 1, 5, 6.
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
public class SubsetSumProblem
{
private int[] w;
private int c;
public SubsetSumProblem(int c, IEnumerable<int> w)
{
if (c < 0) throw new ArgumentOutOfRangeException("Capacity for subset sum problem must be at least 0, but input was: " + c.ToString());
int n = w.Count();
this.w = new int[n];
this.c = c;
IEnumerator<int> pwi = w.GetEnumerator();
pwi.MoveNext();
for (int i = 0; i < n; i++, pwi.MoveNext())
this.w[i] = pwi.Current;
}
public int[] SolveSubsetSumProblem()
{
int n = w.Length;
int[] r = new int[c+1];
BitArray R = new BitArray(c+1);
R[0] = true;
BitArray Rp = new BitArray(c+1);
for (int d =0; d<=c ; d++) r[d] = 0;
for (int j = 0; j < n; j++)
{
Rp.SetAll(false);
for (int k = 0; k <= c; k++)
if (R[k] && k + w[j] <= c) Rp[k + w[j]] = true;
for (int k = w[j]; k <= c; k++) // since Rp[k]=false for k<w[j]
if (Rp[k])
{
if (!R[k]) r[k] = j;
R[k] = true;
}
}
int capacity_used= 0;
for(int d=c; d>=0; d--)
if (R[d])
{
capacity_used = d;
break;
}
List<int> result = new List<int>();
while (capacity_used > 0)
{
result.Add(r[capacity_used]);
capacity_used -= w[r[capacity_used]];
} ;
if (capacity_used < 0) throw new Exception("Subset sum program has an internal logic error");
return result.ToArray();
}
}
Ich bin nicht in der Lage Um deine Frage zu verstehen, kannst du hier bitte ein Beispiel geben. Hier ist was ich verstehe, [3,5,2,6,1,8,15,18,4] wenn K ist 3 M ist 15, dann kann ich 8,2,4 auswählen, ist das was die Antwort sein sollte? – AKS
@AKS Frage ist ... wir können nur K Länge Teilmengen ... und aus diesen K Länge Teilmengen, die Teilmenge gibt maximale Summe ... unter der Bedingung, dass die Summe ist weniger als M – Shivendra
ok, so per Beispiel Ich habe gegeben, wenn k 3 ist, dann aus allen Teilmengen der Länge 3, die maximale Summe, aber weniger als 15 hat. Danke !! – AKS