Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1628to1632
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Variabilisierung der Packstücke beim Rucksackprobl

Variabilisierung der Packstücke beim Rucksackprobl
26.06.2018 14:33:22
CO-Robert
Variabilisierung der Packstücke beim Rucksackproblem in VBA
Hallo zusammen,
ich habe mir ein Tool zur Optimierung für einen Produktionsprozess mittels knapsack-Problem im VBA gebaut. Funktioniert mit allen Nebenbedingungen auch tadellos.
Derzeit habe ich alles auf 55 Einzelelemente fix vorgegeben. Die Laufzeit ist dementsprechend lang. Nun gibt es aber auch Fälle, in denen nur 25 oder 15 Einzelelemente zu berücksichtigen sind. Hier würde ich gern die Laufzeit dadurch verkürzen, dass eben nicht alle theoretischen 55 Einzelelemente berücksichtigt werden, sondern nur die, bei denen die Werten für Gewicht und value 0 sind.
Habe derzeit keinen Plan, wie ich das umsetzen könnte.
Hat jemand von euch eine Idee?
Vielen Dank vorab.
VG
CO-Robert

26
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
In Zeile 38..
26.06.2018 14:36:09
UweD
musst du die Reihenfolge tauschen
LG UweD
Kristallkugel ?
26.06.2018 14:49:37
mmat
Wo siehst du den Code ?
genau das ist ja das Problem
26.06.2018 14:59:28
UweD
Ich hätte noch
&ltIronie&gt Meine Antwort &lt/Ironie&gt verwenden sollen
dazu passt aber doch auch dein Antwort weiter unte
26.06.2018 15:05:03
UweD
42
Dazu passt aber doch auch dein Antwort weiter unte
26.06.2018 15:14:22
mmat
Jo, vielleicht sollte er beim Knappsack der 42 auch mehr Beachtung schenken.
AW: Dazu passt aber doch auch dein Antwort weiter unte
26.06.2018 15:33:25
CO-Robert
Hm, weiß ich jetzt nicht, was ich zu den Anmerkungen von UweD und mmat sagen soll ...
Geht es vllt ein wenig konkreter?
AW: Dazu passt aber doch auch dein Antwort weiter unte
26.06.2018 15:37:26
mmat
Hallo Robert,
wie sollen wir dir sagen, wo du die gewünschte Flexibilität in deinen Code einbauen kannst, wenn du diesen nicht veröffentlichst?
Ich bitte um Nachsicht für das Geplänkel am Rande, es ist Dienstag ...
Anzeige
AW: Dazu passt aber doch auch dein Antwort weiter unte
26.06.2018 15:37:35
Daniel
Hi
hast du dir schon mal überlegt wie wir dir bei deinem Code helfen sollen, wenn wir den Code gar nicht kennen?
außerdem ist eine Beispieldatei immer hilfreich, damit man seine Ideen auch mal ausprobieren und testen kann.
Gruß Daniel
AW: Dazu passt aber doch auch dein Antwort weiter unte
26.06.2018 16:19:42
CO-Robert
Hi,
ok, ich habe angenommen, dass es sich bei einer derartigen Fragestellung um eine generelle Routine handelt, in der Art wie P(i) über i=1 bis n, wobei n eben variabel ist.
Aber hier mal der code: (handelt sich hierbei um die b-Version aus dem Entwicklungsstadium, aber prinzipiell gleicher Aufbau)
Sub Planung_Hauptprodukt()
Dim limit As Double, weight As Double, value As Double, totalWeight As Double, maximumValue As  _
Double, anlegermax As Double, anleger As Double
Dim a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z  As Integer
Dim weighta, weightb, weightc, weightd, weighte, weightf, weightg, weighti, weightj, weightk,  _
weightl,
weightm, weightn, weighto, weightp, weightq, weightr, weights, weightt, weightu, weightv,  _
weightw, weightx, weighty, weightz As Double
Dim valuea, valueb, valuec, valued, valuee, valuef, valueg, valuei, valuej, valuek, valuel,  _
valuem,
valuen, valueo, valuep, valueq, valuer, values, valuet, valueu, valuev, valuew, valuex, valuey,  _
valuez As Double
Dim anlegera, anlegerb, anlegerc, anlegerd, anlegere, anlegerf, anlegerg, anlegeri, anlegerj,  _
anlegerk,
anlegerl, anlegerm, anlegern, anlegero, anlegerp, anlegerq, anlegerr, anlegers, anlegert,  _
anlegeru, anlegerv, anlegerw, anlegerx, anlegery, anlegerz As Double
Range("N10").value = 0
Range("B28").value = 0
Range("B30").value = 0
Range("B7").value = 0
Range("B9").value = 0
Range("B26:V26").value = 0
limit = Range("D7").value
anlegermax = Range("D11").value
maximumValue = 0
Range("G10").value = "... bitte warten"
weighti = Range("B2").value
weightj = Range("C2").value
weightk = Range("D2").value
weightl = Range("E2").value
weightm = Range("F2").value
weightn = Range("G2").value
weighto = Range("H2").value
weightp = Range("I2").value
weightq = Range("J2").value
weightr = Range("K2").value
weights = Range("L2").value
weightt = Range("M2").value
weightu = Range("N2").value
weightv = Range("O2").value
weightw = Range("P2").value
weightx = Range("Q2").value
weighty = Range("R2").value
weightz = Range("S2").value
weighta = Range("T2").value
weightb = Range("U2").value
weightc = Range("V2").value
weightd = Range("W2").value
weighte = Range("X2").value
weightf = Range("Y2").value
weightg = Range("Z2").value
valuei = Range("B4").value
valuej = Range("C4").value
valuek = Range("D4").value
valuel = Range("E4").value
valuem = Range("F4").value
valuen = Range("G4").value
valueo = Range("H4").value
valuep = Range("I4").value
valueq = Range("J4").value
valuer = Range("K4").value
values = Range("L4").value
valuet = Range("M4").value
valueu = Range("N4").value
valuev = Range("O4").value
valuew = Range("P4").value
valuex = Range("Q4").value
valuey = Range("R4").value
valuez = Range("S4").value
valuea = Range("T4").value
valueb = Range("U4").value
valuec = Range("V4").value
valued = Range("W4").value
valuee = Range("X4").value
valuef = Range("Y4").value
valueg = Range("Z4").value
For i = 0 To 1
For j = 0 To 1
For k = 0 To 1
For l = 0 To 1
For m = 0 To 1
For n = 0 To 1
For o = 0 To 1
For p = 0 To 1
For q = 0 To 1
For r = 0 To 1
For s = 0 To 1
For t = 0 To 1
For u = 0 To 1
For v = 0 To 1
For w = 0 To 1
For x = 0 To 1
For y = 0 To 1
For z = 0 To 1
For a = 0 To 1
For b = 0 To 1
For c = 0 To 1
For d = 0 To 1
For e = 0 To 1
For f = 0 To 1
For g = 0 To 1
_
weight = weighti * i + weightj * j + weightk * k + weightl * l + weightm * m + weightn * n +
weighto * o + weightp * p + weightq * q + weightr * r + weights * s + weightt * t + weightu * u  _
weightv * v + weightw * w + weightx * x + weighty * y + weightz * z + weighta * a + weightb * b  _
weightc * c + weightd * d + weighte * e + weightf * f + weightg * g
value = valuei * i + valuej * j + valuek * k + valuel * l + valuem * m + valuen * n + valueo *  _
o +
valuep * p + valueq * q + valuer * r + values * s + valuet * t + valueu * u + valuev * v +
valuew * w + valuex * x + valuey * y + valuez * z + valuea * a + valueb * b + valuec * c +
valued * d + valuee * e + valuef * f + valueg * g
anleger = i + j + k + l + m + n + o + p + q + r + s + t + u + v + w + x + y + z + a + b + c
+ d + e + f + g
If value > maximumValue And weight 

Anzeige
die Dim-alle falsch, sonst ganz nett :-)) oT
26.06.2018 16:25:35
robert
AW: die Dim-alle falsch, sonst ganz nett :-)) oT
26.06.2018 16:38:28
CO-Robert
Aha - und was genau ist da alles falsch an den Dim?
Und warum läuft das Ganze dann?
AW: die Dim-alle falsch, sonst ganz nett :-)) oT
26.06.2018 17:01:45
Daniel
Hi
dim x, y as integer 

dimensioniert y als interger und x als Variant, weil für x kein Variablentyp angegeben ist.
Alles funktioniert im Prinzip auch mit Variant-Variablen, welche immer den aktuell benötigten Typ annehmen, aber sie werden durch diese Flexibilität auch deutlich langsamer verarbeitet.
Merkt man normalerweise nicht, aber bei dir könnte es relevant werden
Wenn x und y integer werden sollen, dann musst du das so schreiben:
dim x as integer, y as integer

für die Variable Anpassung deines Codes müsste man die Schleifen als Rekursion aufbauen, dh eine Schleife die sich selbst aufruft.
jeder selbstaufruf ist dann eine Schleife und die Anzahl der Selbstaufrufe kann man steueren.
Gruß Daniel
Anzeige
AW: die Dim-alle falsch, sonst ganz nett :-)) oT
26.06.2018 17:01:47
Daniel
Hi
dim x, y as integer 

dimensioniert y als interger und x als Variant, weil für x kein Variablentyp angegeben ist.
Alles funktioniert im Prinzip auch mit Variant-Variablen, welche immer den aktuell benötigten Typ annehmen, aber sie werden durch diese Flexibilität auch deutlich langsamer verarbeitet.
Merkt man normalerweise nicht, aber bei dir könnte es relevant werden
Wenn x und y integer werden sollen, dann musst du das so schreiben:
dim x as integer, y as integer

für die Variable Anpassung deines Codes müsste man die Schleifen als Rekursion aufbauen, dh eine Schleife die sich selbst aufruft.
jeder selbstaufruf ist dann eine Schleife und die Anzahl der Selbstaufrufe kann man steueren.
Gruß Daniel
Anzeige
AW: die Dim-alle falsch, sonst ganz nett :-)) oT
26.06.2018 17:04:03
UweD
Hallo
ich hab es mir nicht angesehen...
Nur eine Aussage zu DIM:
Dim a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z As Integer
hier wird nur Z als Integer deklariert
Alle Anderen davor als Variant


das gleiche weiter darunter


Dim limit As Double, weight As Double, value As Double, totalWeight As Double, maximumValue As   _
_
Double, anlegermax As Double, anleger As Double
ist Richtig
aber value als Variable würde ich nicht verwenden; ist Bestandteil der Pogrammiersprache
Du kannst aber Abkürzungen verwenden
Dim limit#, weight#, value#, totalWeight#, maximumValue#, anlegermax#, anleger#
Dim a%, b%, c%, d%, e%, f%, g%, i%, j%, k%, l%, m%, n%, o%, p%, q%, r%, s%, t%, u%, v%, w%, x%, y%, z%
siehe z.B. https://docs.microsoft.com/de-de/dotnet/visual-basic/programming-guide/language-features/data-types/type-characters

Und warum läuft das Ganze dann?

Weil es auf mit variant auch läuft
LG UweD
Anzeige
Rekursion
26.06.2018 17:01:12
mmat
Hallo Robert,
nun mal ernsthaft:
Die dim sind teilweise falsch weil
Dim x, y, z as integer

ist identisch mit
dim x as variant, y as variant, z as integer

Ja, eigentlich nicht falsch, sondern nur: "wahrscheinlich so nicht gewollt, funktioniert aber meistens."
Die Anzahl der Elemente ist bei dir durch die Menge der For-Next Schleifen fest verdrahtet, falls die Anzahl variabel sein soll, dann muß ein rekursiver Algorythmus her.
Ich hab sowas mal vor ewigen Zeiten zusammengenagelt und stell das jetzt mal kommentarlos hier 'rein. Das ganze basiert auf einer Liste von Elementen mit den Spalten Name, Wert und Gewicht, wobei Name ein einzelner Großbuchstabe sein muß (Damit derzeit maximal 26 Elemente). Guck mal ob du damit was anfangen kannst.
Option Explicit
Dim count
Type Result
Items As String
Value As Long
Weight As Long
End Type
Dim FinalResult As Result, Limit As Long, anz As Long, g() As Long, rw As Long
Sub Autput(r As Result)
rw = rw + 1
If r.Value > 0 Then
Cells(rw, 1) = r.Items
Else
Cells(rw, 1) = "(" + r.Items + ")" 'Verworfen
End If
Cells(rw, 2) = r.Value
Cells(rw, 3) = r.Weight
End Sub
Function EvaluateCombi(s As String) As Result
Dim r As Result, n As Integer, i As Integer
r.Items = s
r.Value = 0
r.Weight = 0
For n = 1 To Len(s): i = Asc(Mid(s, n, 1)) - 64: r.Value = r.Value + g(i, 0): r.Weight = r. _
Weight + g(i, 1): Next
If r.Weight > Limit Then r.Value = -1
EvaluateCombi = r
End Function
Sub Combi(ByVal Cur As String, ByVal Wk As String)
Dim i As Integer, r As Result
i = 0
While i  FinalResult.Value) Or ((r.Value = FinalResult.Value) And (r.Weight  0) Then Autput r
Combi Cur + Mid(Wk, i, 1), Mid(Wk, i + 1) 'Left(Wk, i - 1) + Mid(Wk, i + 1)
Wend
End Sub
Sub AlleKombinationen()
Dim n As Integer, s As String, rws As Long
Limit = Range("Limit")
anz = Range("Güter").Rows.count
ReDim g(anz, 1): s = ""
For n = 1 To anz: s = s + Range("Güter").Cells(n, 1): g(n, 0) = Range("Güter").Cells(n, 2): g( _
n, 1) = Range("Güter").Cells(n, 3): Next
rw = Range("Limit").Cells(1, 1).Row + 1: Range(Cells(rw, 1), Cells(5000, 3)).ClearContents:  _
rw = rw + 1
rws = rw
Cells(rw, 1) = "Kombi": Cells(rw, 2) = "Wert": Cells(rw, 3) = "Gewicht"
count = 0: FinalResult.Items = "": FinalResult.Value = 0: FinalResult.Weight = 0
Combi "", s
Range(Cells(rws, 1), Cells(rw - 1, 3)).Sort Key1:=Range("B13"), Order1:=xlDescending, Key2:= _
Range("C13"), Order2:=xlAscending, Header:=xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
rw = rw + 1: Autput FinalResult: rw = rw + 1: Cells(rw, 1) = count
End Sub

Anzeige
ohne Rekursion
26.06.2018 18:53:51
Daniel
HI
dein Code ist eigentlich ganz einfach.
du bildest alle möglichen Kombinationen und vergleichst die Summe der Gewichte und der Werte.
das geht auch flexibel mit zwei geschachtelten Schleifen.
Die Anzahl der Elemente gibst du in der Variablen Anz vor.
die Zellen ab B2 müssen dann entsprechen nach rechts gefüllt werden.
bei bedarf kann man dann die Anzahl noch anhand der gefüllten Zellen ermitteln lassen.
(
Sub knapsack()
Dim Objekt
Dim Gewicht
Dim Wert
Dim Anz As Long
Dim limAnzahl As Long
Dim limGewicht As Double
Dim sumAnzahl As Long
Dim sumGewicht As Double
Dim sumWert As Double
Dim ergWert As Double
Dim ergGewicht As Double
Dim ergID As Double
Dim ID As Double
Dim x As Double
Dim i As Long, n As Long
limAnzahl = Range("D11").Value ' Maxmiale Anzah an Ojekten im Ergebnis
limGewicht = Range("D7").Value ' zulässsiges Gewicht
Anz = 8 'Anzahl der vorhandenen Objekte
ReDim Gewicht(Anz - 1) As Double
ReDim Wert(Anz - 1) As Double
For i = 0 To Anz - 1
Gewicht(i) = Range("B2").Offset(0, i).Value
Wert(i) = Range("B4").Offset(0, i).Value
Next
For ID = 1 To 2 ^ Anz - 1
If ID = 7 Then Stop
sumGewicht = 0
sumWert = 0
sumAnzahl = 0
For n = 0 To Anz - 1
x = 2 ^ n
If (ID And x) = x Then
sumGewicht = sumGewicht + Gewicht(n)
sumWert = sumWert + Wert(n)
sumAnzahl = sumAnzahl + 1
End If
Next
If sumGewicht  ergWert Then
ergWert = sumWert
ergGewicht = sumGewicht
ergID = ID
End If
End If
End If
Next ID
For i = 0 To Anz - 1
Range("B5").Offset(0, i).Value = -1 * ((ergID And 2 ^ i) = 2 ^ i)
Next
Range("B7").Value = ergGewicht
Range("B9").Value = ergWert
End Sub
das Prinzip ist hier, dass man alle möglichen Kombinationen hier auch einfach über die Schleife
For x = 1 to 2 ^ Anzahl -1
darstellen kann. ob ein Objekt jetzt in der Kombination vorkommt oder nicht, prüft man dann so:
jedem Objekt wird ein WErt der 2-Potentzreihe zugeordet (1, 2, 4, 8 .... 2^n). mit dem AND-Operator kann man dann ermitteln, ob das jeweilige Bit in der Zahl die die Kombination darstellt, gesetzt ist oder nicht (in VBA kann AND mehr als nur 2 Wahrheitswerte kombinieren, es führt mit Zahlen einen Bit-Weisen vergleich aus).
Gruß Daniel
Anzeige
AW: ohne Rekursion
26.06.2018 19:12:14
Daniel
die Zeile mit dem STOP kanns du löschen, die war nur zum testen drin.
Gruß Daniel
AW: ohne Rekursion
26.06.2018 21:37:24
CO-Robert
Hallo zusammen,
Zunächst vielen Dank für die ernsthaften Antworten und Tipps.
ZuErklärung: wegen Mangel an VBA-Kenntnissen habe ich den grundsätzlichen Code (bezog sich auf 10 Elemente) 1:1 übernommen, also seht mir die Fehler in den Dim‘s nach.
Die Vorschläge für die Schleifen und Rekursaionen werde ich mir in Ruhe ansehen und versuchen in mein Beispiel zu implementieren.
Ich melde mich hier wieder, wenn ich es gewippt habe - oder wenn ich nicht mehr weiter weiss ... ;-))
Schönen Abend euch
VG CO-Robert
Anzeige
Danke für die Rückmeldung o.T
27.06.2018 09:19:56
mmat
AW: Danke für die Rückmeldung o.T
28.06.2018 09:34:14
CO-Robert
Hallo zusammen,
also ich hab den Code von Daniel eingebaut und es funktioniert - dachte ich zumindest.
Bei einer Anzahl von 34 Objekten bekomme ich den Debugger mit ner Überlauf-Meldung - Laufzeitfehler'6'
For ID = 1 To 2 ^ Anz - 1
sumGewicht = 0
sumWert = 0
sumAnzahl = 0
For n = 0 To Anz - 1
x = 2 ^ n
If (ID And x) = x Then "an dieser Stelle bricht das Ganze ab"
sumGewicht = sumGewicht + Gewicht(n)
sumWert = sumWert + Wert(n)
sumAnzahl = sumAnzahl + 1
End If ...
Bei 34 Objekten sind es ja auch mal eben schlappe 17,2 Mrd. Kombinationen ... zu schlapp meinen Büro-Rechner ... trotz i5 3,4 GHz und 8GB RAM auf 64-bit ...
mit 24 Objekten läuft es problemlos und liefert das gewünschte Ergebnis. Ich überlege jetzt, die Ermittlung der Anzahl vorhandener Objekte auf max. 25 zu beschränken.
Danke an mmat und Daniel ...
Anzeige
AW: Danke für die Rückmeldung o.T
28.06.2018 10:03:43
Daniel
Hi
scheint so, als würde die AND-Funktion intern mit dem Datentyp LONG arbeiten und dann geht da nicht mehr als c.a. 2 Mrd Kombinationen.
dh maximal 30 oder 31 Objekte kannst du so verarbeiten.
wenn du mehr brauchst, müsstest du dir die AND-Funktion selber programmieren.
dh die Zahlen ins 2er-Format wandeln und dann überprüfen, welche Bits bei beiden Zahlen gesetzt sind.
Gruß Daniel
AW: Danke für die Rückmeldung o.T
28.06.2018 10:10:20
CO-Robert
Hi Daniel,
hatte ich mir auch schon überlegt, aber nach derzeitigem Stand sind 30 Objekte völlig ausreichend.
Die Einzelwerte der Dim wert der Objekte 20-30 liegen im Schnitt nur bei 10-15% der maximalen Wertigekeit der ersten 10-15 Objekte.
Von daher würde hier lediglich das Einzelgewicht im Rahmen der Gewichtsmaximierung eine Rolle spielen.
VG und Danke nochmals.
maximale Obergrenze für meine Lösung
28.06.2018 10:17:30
Daniel
sind 49 Objekte, auch wenn du dir die AND-Funktion für größere Zahlen nachbaust.
bei 50 und mehr Objekten hat die Anzahl der Kombinationen mehr als 15 Stellen und kann von Excel nicht mehr vollständig dargestellt werden, denn der Datentyp Double kann maximal 15 stellen verarbeiten und rundet bei größeren Zahlen, was dein Ergebnis verfälschen würde.
dh du solltest dir mal auf jeden Fall die Rekursionslösung von MMat anschauen.
Gruß Daniel
Die Anzahl der Kombinationen beträgt 2^n-1
28.06.2018 10:04:54
mmat
Hallo,
zu Daniels Ansatz kann ich nicht viel sagen, außer das er die Objekte als Bit in einer großen Zahl darstellt. Und da ist bei 32 Objekten wahrscheinlich Schluss.
Ich hab meinen Ansatz mal mit 55 Objekten getestet, nach einer kleinen Modifikation läuft der recht flott. Die Laufzeit ist natürlich stark von den Gegebenheiten des Problems abhängig.
Vielleicht hat Daniel ja noch eine Idee
AW: Die Anzahl der Kombinationen beträgt 2^n-1
28.06.2018 10:13:34
CO-Robert
Hi,
ok. Kannst du die Modifikation bitte mal posten?
Hatte mich bisher nur an Daniels Version gewygt, weil für mich als VBA-Laie der Code üvbersichtlicher und logischer war, also eher mathematisch nachvollziehbar ...
Würde aber auch gern deine Version testen wollen ... ;-)
VG
Optimierter Ansatz
28.06.2018 10:34:03
mmat
Erstmal ein Stück Code (einfach mal auf die schnelle hingeschmiert) um ein Problem zu erzeugen, Limit und Anzahl können von Hand verändert werden:
Sub ProblemErzeugen()
Dim n As Long, i As Long, z As Long, ok As Boolean
Dim zz1() As Long, zz2() As Long
Workbooks.Add
Cells(1, 1) = "Name": Cells(1, 2) = "Wert": Cells(1, 3) = "Gewicht"
n = 55
ReDim zz1(n): For i = 1 To n: zz1(i) = i: Next
ReDim zz2(n): For i = 1 To n: zz2(i) = i: Next
For i = 1 To n
Cells(i + 1, 1) = Chr(i + 64)
Do
z = Int(Rnd * n) + 1
ok = zz1(z) > 0
If ok Then zz1(z) = -1
Loop Until ok
Cells(i + 1, 2) = z * 5
Do
z = Int(Rnd * n) + 1
ok = zz2(z) > 0
If ok Then zz2(z) = -1
Loop Until ok
Cells(i + 1, 3) = z * 100
Next
Range(Cells(2, 1), Cells(n + 1, 3)).Name = "Güter"
Cells(n + 3, 1) = "Limit": Cells(n + 3, 2) = (n + 5) * 100: Cells(n + 3, 2).Name = "Limit"
Cells(n + 4, 1) = "Anzahl": Cells(n + 4, 2) = n: Cells(n + 4, 2).Name = "Anzahl"
End Sub
Dann der optimierte Code, ich hab alles rausgeschmissen, was Zeit kostet (Ausgabe von Teilergebnissen) und einen Abbruch eingebaut, wenn das Limit bei einer bestimmten Anfangssequenz überschritten wurde.
Option Explicit
Type Result
Items As String
Value As Long
Weight As Long
End Type
Dim FinalResult As Result, Limit As Long, Anz As Long, g() As Long, rw As Long, count As Double
Sub Autput(r As Result)
rw = rw + 1
If r.Value > 0 Then
Cells(rw, 1) = r.Items
Else
Cells(rw, 1) = "(" + r.Items + ")" 'Verworfen
End If
Cells(rw, 2) = r.Value
Cells(rw, 3) = r.Weight
End Sub
Function EvaluateCombi(s As String) As Result
Dim r As Result, n As Integer, i As Integer
r.Items = s
r.Value = 0
r.Weight = 0
For n = 1 To Len(s): i = Asc(Mid(s, n, 1)) - 64: r.Value = r.Value + g(i, 0): r.Weight = r. _
Weight + g(i, 1): Next
If r.Weight > Limit Then r.Value = -1
EvaluateCombi = r
End Function
Sub Combi(ByVal Cur As String, ByVal Wk As String)
Dim i As Integer, r As Result
i = 0
While i  FinalResult.Value) Or ((r.Value = FinalResult.Value) And (r.Weight  0) Then Combi Cur + Mid(Wk, i, 1), Mid(Wk, i + 1): 'Autput r 'nur dann in die  _
nächste Iteration, wenn das Limit noch nicht überschritten ist
Wend
End Sub
Sub AlleKombinationen() '2^n-1
Dim n As Integer, s As String, rws As Long
Dim t As Date
Limit = Range("Limit")
Anz = Range("Anzahl")  'Range("Güter").Rows.count
ReDim g(Anz, 1): s = ""
For n = 1 To Anz: s = s + Range("Güter").Cells(n, 1): g(n, 0) = Range("Güter").Cells(n, 2): g( _
n, 1) = Range("Güter").Cells(n, 3): Next
rw = Range("Limit").Cells(1, 1).Row + 2: Range(Cells(rw, 1), Cells(5000, 3)).ClearContents:  _
rw = rw + 1
rws = rw
Cells(rw, 1) = "Kombi": Cells(rw, 2) = "Wert": Cells(rw, 3) = "Gewicht"
Application.ScreenUpdating = False: t = Now()
count = 0: FinalResult.Items = "": FinalResult.Value = 0: FinalResult.Weight = 0
Combi "", s
'  Range(Cells(rws, 1), Cells(rw - 1, 3)).Sort Key1:=Range("B13"), Order1:=xlDescending, Key2:= _
Range("C13"), Order2:=xlAscending, Header:=xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
rw = rw + 1: Autput FinalResult: Cells(rw + 1, 1) = count: Cells(rw + 2, 1) = Now() - t:  _
Cells(rw + 2, 1).NumberFormat = "mm:ss"
Application.ScreenUpdating = True
Application.StatusBar = False
End Sub
Bei meinem zufällig generierten Problem beträgt die Gesamtmasse 154000. Je geringer die Differenz zwischen der Gesamtmasse und dem Limit, desto länger die Laufzeit.
Vielleicht kannst du ja mal dein Problem posten ...

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige