Rucksackproblem (Knapsack)

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Iomegan
Beiträge: 6
Registriert: So Mai 13, 2012 10:58 pm

Rucksackproblem (Knapsack)

Beitrag von Iomegan » So Mai 13, 2012 11:10 pm

Hallo Leute,

Es gibt hier diese schöne Beschreibung des Rucksackproblems: http://www.proggen.org/doku.php?id=algo:knapsack

Der dynamische Algorithmus macht was er soll und ich habe die Theorie weitestgehend verstanden, auch wenn ich manchmal noch stark nachdenken muss :)

Mein Problem ist, dass ich nicht nur wissen möchte was am Ende der größte Wert ist, sondern auch welche Gegenstände genau nun im Rucksack sind. Müsste doch eigentlich recht einfach sein rauszufinden wessen Werte letztendlich zusammen addiert worden sind.

Ich hab schon einiges hin und her probiert, finde aber keine Lösung. :roll:

Hat jemand vielleicht einen Tipp für mich?


Hier noch mal der C-Code:

Code: Alles auswählen

#include <stdio.h>


// currentVolume: Das restliche (freie) Volumen im Rucksack
// i: Aktueller Gegenstand
// Return value: Maximaler Wert mit bzw. ohne den aktuellen Gegenstand
int knapsack( const int currentVolume, const int i );

// Maximale Anazahl an Gegenständen
const int maxN = 300;
// Maximales Volumen des Rucksacks
const int maxV = 1000;
// Anzahl an Byte für unseren Dynamisierungs-Array
const int resultLength = ( maxV + 1 ) * sizeof( int );

// Volumen des Rucksacks
int V;
// Anzahl an Gegenständen
int n;
// Volumen der einzelnen Gegenstände
int v[maxN];
// Werte der einzelnen Gegenstände
int w[maxN];
// Gespeicherte Ergebnisse von bisherigen Berechnungen
int results[maxN][maxV + 1];

int main()
{
    // Eingabe der Daten
    printf("Eingabe [Volumen Rucksack] [Anzahl Gegenstaende]:\n");
    fscanf( stdin, "%d %d", &V, &n );
    for( int i = 0; i < n; i++ ){
        printf("\n%d. Gegenstaend: [Volumen] [Wert]\n", i+1);
        fscanf( stdin, "%d %d", &( v[i] ), &( w[i] ) );
    }
    // Initialisierung des Dynamisierungs-Arrays
    for( int i = 0; i < n; i++ )
        memset( results[i], -1, resultLength );
    // Berechnung und Ausgabe
    fprintf( stdout, "\n%d\n", knapsack( V, 0 ) );
  
    
    return 0;
}

int max(int a, int b)
{
    return (a < b) ? b : a;
}

int knapsack( const int currentVolume, const int i )
{
    // Prüfen, ob ein gültiger Index übergeben wurde
    if( i < n )
    {
        // Prüfen, ob der Wert bereits berechnet wurde.
        if( results[i][currentVolume] != -1 ){
            return results[i][currentVolume];
        }
        // Berechne Wert ohne den aktuellen Gegenstand
        int a = knapsack( currentVolume, i + 1 );
        // Berechne Wert mit dem aktuellen Gegenstand, wenn noch Platz dafür ist
        int b = 0;
        if( currentVolume - v[i] >= 0 ){
            b = w[i] + knapsack( currentVolume - v[i], i + 1 );
        }
        // Maximum der Berechnung wird gespeichert und zurückgegeben
        results[i][currentVolume] = max(a, b);
        return results[i][currentVolume];
    }
    
    return 0;
}

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Rucksackproblem (Knapsack)

Beitrag von nufan » Mo Mai 14, 2012 1:36 am

Hallo :)
Iomegan hat geschrieben:Es gibt hier diese schöne Beschreibung des Rucksackproblems: http://www.proggen.org/doku.php?id=algo:knapsack

Der dynamische Algorithmus macht was er soll und ich habe die Theorie weitestgehend verstanden, auch wenn ich manchmal noch stark nachdenken muss :)
Schön, dass dir mein Artikel gefällt :) Falls es Kritik positiver oder negativer Art gibt, nur her damit :)
Iomegan hat geschrieben:Mein Problem ist, dass ich nicht nur wissen möchte was am Ende der größte Wert ist, sondern auch welche Gegenstände genau nun im Rucksack sind. Müsste doch eigentlich recht einfach sein rauszufinden wessen Werte letztendlich zusammen addiert worden sind.

Ich hab schon einiges hin und her probiert, finde aber keine Lösung. :roll:
Die Lösung dafür ist recht kompliziert und nicht grade offensichtlich. Leider bin ich noch nicht dazu gekommen das in den Artikel einzubaun.

Hier die Erklärung (ich werde das bei Gelegenheit ins Wiki übertragen):
Vorweg: Dein gesuchtes Ergebnis ist 1, 5 und 9. Die Gegenstände mit diesen Nummern werden verwendet.
An diesem Punkt solltest du dir ganz bewusst werden was deine Dynamisierungsmatrix (results[][]) überhaupt ist. Sie speichert den maximalen Wert im Rucksack an einem bestimmten Index und Volumen. Sehen wir uns deine Dynamisierungsmatrix an (ich hab sie etwas kleiner gemacht: maxN = 10, maxV = 30). Dafür hab ich folgenden Code, den du einfach nach dem Aufruf deiner Rekursion in main einfügen kannst:

Code: Alles auswählen

fprintf( stdout, "   " );
for( int i = 0; i < maxN; i++ )
  fprintf( stdout, "%2d ", i );
fprintf( stdout, "\n" );
for( int i = 0; i < maxV + 1; i++ )
{
  fprintf( stdout, "%2d ", i );
  for( int j = 0; j < maxN; j++ )
    fprintf( stdout, "%2d ", results[j][i] );
  fprintf( stdout, "\n" );
}
Ausgabe:

Code: Alles auswählen

    0  1  2  3  4  5  6  7  8  9 
 0 -1 -1 -1 -1 -1 -1  0  0  0  0 
 1 -1 -1 -1 -1 -1  0  0  0  0  0 
 2 -1 -1 -1 -1 -1  0  0  0  0  0 
 3 -1 -1 -1 -1 -1 -1  0  0  0  0 
 4 -1 -1 -1 -1 -1  0  0  0  0  0 
 5 -1 -1 -1 -1 -1 -1  0  0  0  0 
 6 -1 -1 -1 -1  0  0  0  0  0  0 
 7 -1 -1 -1 -1 -1  0  0  0  0  0 
 8 -1 -1 -1 -1 -1 -1  0  0  0  0 
 9 -1 -1 -1 -1 -1  0  0  0  0  0 
10 -1 -1 -1 -1 -1  0  0  0  0  0 
11 -1 -1 -1 -1 10  5  0  0  0  0 
12 -1 -1 -1 -1 10 10 10  0  0  0 
13 -1 -1 -1 -1 -1 -1 10  0  0  0 
14 -1 -1 -1 10 10 10 10  0  0  0 
15 -1 -1 -1 -1 -1 20 20 20 20  0 
16 -1 -1 -1 -1 20 20 20 20 20  0 
17 -1 -1 -1 -1 20 20 20 20 20  0 
18 -1 -1 -1 -1 -1 -1 -1 20 20  0 
19 -1 -1 -1 20 20 20 20 20 20  0 
20 -1 -1 20 20 20 20 20 20 20  0 
21 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 
22 -1 -1 -1 -1 20 20 20 20 20  0 
23 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 
24 -1 -1 -1 25 20 20 20 20 20  0 
25 -1 30 30 30 30 20 20 20 20  0 
26 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 
27 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 
28 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 
29 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 
30 38 38 37 37 37 37 37 37 20 20
(Das wird im Forum nicht schön dargestellt, wenn es dich stört kopier es einfach in einen Texteditor)
Spalten sind Gegenstände, Zeilen die jeweiligen (belegte) Volumen. Die erste Spalte ist der Volumen-Index, die erste Zeile der Gegenstands-Index.
Wenn du genau darüber nachdenkst, kommst du auf folgendes: Dein maximaler Wert im Rucksack steht immer ganz links unten, in results[0][maxV] (Füllst du den Rucksack nicht komplett, musst du nach dem Index anstelle von maxV suchen, an dem results[0] maximal ist.). Warum? Weil dieser Wert als letztes berechnet wird. Der Rekursionbaum geht zuerst durch alle Äste bis an die Blätter und kommt dann zur Wurzel zurück. Schritt für Schritt werden dann die Werte in die Matrix eingefügt, der Wert results[0][maxV] ganz zum Schluss. Da du in allen Rekursionen davor immer das Maximum genommen hast, erhältst du hier das größte Maximum aller möglichen Rekursionswege (Anmerkung: In results[1][maxV] steht ebenfalls das Maximum. Das hat einen ganz einfachen Grund: Gegenstand 0 und 1 sind identisch. Da nur einer der beiden Gegenstände ausgewählt wird, kann das Maximum mit beiden Gegenständen gebildet werden.).
So, nun wissen wir aber nicht wirklich mehr als zuvor. Wie kann man prüfen, ob der erste Gegenstand (Volumen 5, Wert 8) in den Rucksack gegeben wurde? Ganz einfach, wir gehen genau den umgekehrten Weg. Wir tun einfach so, als würden wir den Gegenstand wieder aus dem Rucksack nehmen und schauen, ob wir ein korrektes Ergebnis bekommen.
Fangen wir beim 1. Gegenstand an. Wir sind noch immer ganz links unten, bei results[0][30]. Wenn wir jetzt den Gegenstand rausnehmen, bekommen wir wieder 5 an freien Volumen dazu. Ziehen wir von unserem belegten Volumen 5 ab, landen wir in der Zeile mit dem Index 25. Schauen wir nun in die nächste Spalte (results[1][25]), sehen wir dort den Wert 30. Was bedeutet dieser Wert? Das ist der Wert in unserem Rucksack ohne den 1. Gegenstand (38 - 8 = 30). An dieser Stelle steht wiederum das Maximum für das aktuelle Volumen und den aktuellen Gegenstand. Da die Rückrechnung korrekt ist, haben wir unseren Gegenstand in der Rekursion zuvor ausgewählt.
Wir haben den 1. Gegenstand zurückgerechnet und sind beim Index [1][25]. Versuchen wir das gleiche nochmal für den 2. Gegenstand, der ebenfalls das Volumen 5 und den Wert 8 hat. Nehmen wir den 2. Gegenstand ebenfalls wieder raus, landen wir bei results[2][20], wo wir den Wert 20 finden. Das passt aber nicht. Wenn wir von unserem aktuellen Wert im Rucksack 8 abziehen, bekommen wir 22 (30 - 8) und nicht die angegebenen 20. Dieser Gegenstand war also nicht im Rucksack. Wie gehts jetzt weiter? Wir bleiben in unserer Zeile 25 und gehen einfach zum nächsten Gegenstand (in die nächste Spalte). In results[2][25] haben wir wieder den Wert 30. Das passt, denn wir hatten den Gegenstand nicht im Rucksack, also hat sich der Wert auch nicht verändert. Die Rechnung ohne den 2. Gegenstand ist wiederum korrekt.
Wenn du dieses Schema für alle Gegenstände weiterführst, kommst du zu den gesuchten Gegenständen.

Da das etwas viel war, nochmal zusammenfassend:
1) Rekursion durchführen.
2) Maximalen Wert in Spalte 0 suchen, sollte mit dem Ergebnis der Rekursion übereinstimmen.
3) Volumen des aktuellen Gegenstands vom belegten Gegenstand abziehen. Ist der Wert im Rucksack korrekt?
3.1) Ist die Rechnung korrekt, war der Gegenstand im Rucksack. Volumen abziehen und zum nächsten Gegenstand.
3.2) Ist die Rechnung nicht korrekt, bleibt das Volumen gleich und man geht einfach zum nächsten Gegenstand.
4) Schritt 3 für alle Gegenstände wiederholen.

Eine Implementierung könnte so aussehen (Es wird der Einfachheit halber angenommen, dass der Rucksack komplett gefüllt wurde):

Code: Alles auswählen

int r = knapsack( V, 0 );
// Rucksack ist komplett gefüllt -> belegtes Volumen ist das maximale Volumen
int currentVolume = maxV;
// Über alle Gegenstände iterieren (-1, weil mit i+1 gerechnet wird)
for( int i = 0; i < maxN - 1; i++ )
{
  // Stimmt der Wert an der neuen Position?
  // aktueller Wert im Rucksack - Wert des aktuellen Gegenstands == Maximum für diesen Gegenstand mit dem neuen Volumen
  if( r - w[i] == results[i + 1][currentVolume - v[i]] )
  {
    fprintf( stdout, "selecting %d (%d / %d)\n", i + 1, v[i], w[i] );
    r -= w[i];
  }
  else
    fprintf( stdout, "NOT selecting %d (%d / %d)\n", i + 1, v[i], w[i] );
}
Ausgabe:

Code: Alles auswählen

selecting 1 (5 / 8)
NOT selecting 2 (5 / 8)
NOT selecting 3 (6 / 6)
NOT selecting 4 (8 / 5)
selecting 5 (10 / 10)
NOT selecting 6 (11 / 5)
NOT selecting 7 (12 / 10)
NOT selecting 8 (15 / 17)
selecting 9 (15 / 20)
Probe: 8 + 10 + 20 = 38 == Ergebnis der Rekursion

Ich hoffe ich habe dich nicht zu sehr verwirrt, aber das war die Antwort auf deine Frage :) Sollte es Fragen geben, nur her damit :)

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Rucksackproblem (Knapsack)

Beitrag von Xin » Mo Mai 14, 2012 9:07 am

Soviel Text... :-) War es nicht einfacher, den Artikel entsprechend zu erweitern? ^^

Welcome onboard, Iomegan.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Rucksackproblem (Knapsack)

Beitrag von nufan » Mo Mai 14, 2012 9:49 am

Xin hat geschrieben:Soviel Text... :-) War es nicht einfacher, den Artikel entsprechend zu erweitern? ^^
Naja ich schätze es wird bestimmt Rückfragen geben, außerdem hab ich das jetzt nur mal "schnell" so hingeschrieben ^^

Iomegan
Beiträge: 6
Registriert: So Mai 13, 2012 10:58 pm

Re: Rucksackproblem (Knapsack)

Beitrag von Iomegan » Mo Mai 14, 2012 10:12 am

Das ging ja schnall :) Vielen Dank für die ausführliche Antwort!

Ich muss das erst mal Stück für Stück nachvollziehen.
Dabei sehe ich schon das nächste Problem kommen. Ich wollte das ganze später so abwandeln, dass es möglich ist auch reelle Zahlen mit Nachkommastellen als Volumen zu nehmen. Dann wäre das mit der Matrix sicherlich problematisch. Hmm...

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Rucksackproblem (Knapsack)

Beitrag von nufan » Mo Mai 14, 2012 10:16 am

Iomegan hat geschrieben:Ich muss das erst mal Stück für Stück nachvollziehen.
Kein Problem, lass dir Zeit :)
Iomegan hat geschrieben:Dabei sehe ich schon das nächste Problem kommen. Ich wollte das ganze später so abwandeln, dass es möglich ist auch reelle Zahlen mit Nachkommastellen als Volumen zu nehmen. Dann wäre das mit der Matrix sicherlich problematisch. Hmm...
http://en.wikipedia.org/wiki/Hash_table
:)

Iomegan
Beiträge: 6
Registriert: So Mai 13, 2012 10:58 pm

Re: Rucksackproblem (Knapsack)

Beitrag von Iomegan » Mo Mai 14, 2012 10:21 am

Lustig, momentan sieht meine matrix noch so aus:

Code: Alles auswählen

Eingabe [Volumen Rucksack] [Anzahl Gegenstaende]:
30 10

1. Gegenstaend: [Volumen] [Wert]
5 8

2. Gegenstaend: [Volumen] [Wert]
5 8

3. Gegenstaend: [Volumen] [Wert]
6 6

4. Gegenstaend: [Volumen] [Wert]
8 5

5. Gegenstaend: [Volumen] [Wert]
10 10

6. Gegenstaend: [Volumen] [Wert]
11 5

7. Gegenstaend: [Volumen] [Wert]
12 10

8. Gegenstaend: [Volumen] [Wert]
15 17

9. Gegenstaend: [Volumen] [Wert]
15 20

10. Gegenstaend: [Volumen] [Wert]
30 20

38

    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 
 0 -1 -1 -1 -1 -1 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 1 -1 -1 -1 -1 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 2 -1 -1 -1 -1 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 3 -1 -1 -1 -1 -1 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
usw.
:o

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Rucksackproblem (Knapsack)

Beitrag von nufan » Mo Mai 14, 2012 10:31 am

Selbstzitat ^^
nufan hat geschrieben:Sehen wir uns deine Dynamisierungsmatrix an (ich hab sie etwas kleiner gemacht: maxN = 10, maxV = 30).

Iomegan
Beiträge: 6
Registriert: So Mai 13, 2012 10:58 pm

Re: Rucksackproblem (Knapsack)

Beitrag von Iomegan » Mo Mai 14, 2012 2:51 pm

Hmm, funktioniert bei mir nicht. Bekomme immer NOT selecting...

Ich glaub ich bin zu doof hierfür :( Versuch das jetzt seit heute morgen.

Dadurch dass das ganze rekursiv ist, will das nur schwer in meinen Kopf rein.

Hab inzwischen dies hier gefunden:

Code: Alles auswählen

#include <stdio.h>

#define max(a,b) (a > b ? a : b)

int matrix[100][100] = {0};
int picks[100][100] = {0};

int knapsack(int nItems, int size, int weights[], int values[]){
    int i,j;
    
    for (i=1;i<=nItems;i++){
        for (j=0;j<=size;j++){
            if (weights[i-1]<=j){
                matrix[i][j] = max(matrix[i-1][j],values[i-1]+matrix[i-1][j-weights[i-1]]);
                if (values[i-1]+matrix[i-1][j-weights[i-1]]>matrix[i-1][j])
                    picks[i][j]=1;
                else
                    picks[i][j]=-1;
            }
            else{
                picks[i][j] = -1;
                matrix[i][j] = matrix[i-1][j];
            }
        }
    }
    
    return matrix[nItems][size];
    
}

void printPicks(int item, int size, int weights[]){
    
    while (item>0){
        if (picks[item][size]==1){
            printf("%d ",item-1);
            item--;
            size -= weights[item];
        }
        else{
            item--;
        }
    }
    
    printf("\n");
    
    return;
}

int main(){
    int nItems = 10;
    int knapsackSize = 30;
    int weights[10] = {5,5,6,8,10,11,12,15,15,30};
    int values[10] = {8,8,6,5,10,5,10,17,20,20};
    
    printf("Max value = %d\n",knapsack(nItems,knapsackSize,weights,values));
    printf("Picks were: ");
    printPicks(nItems,knapsackSize, weights);
    
    return 0;
}
Da steige ich irgendwie besser durch :D

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Rucksackproblem (Knapsack)

Beitrag von nufan » Mo Mai 14, 2012 8:56 pm

Iomegan hat geschrieben:Hmm, funktioniert bei mir nicht. Bekomme immer NOT selecting...
Eigenartig... ich hab den Code den du gepostet hast übernommen, geändert und die Eingabedaten vom Wiki übernommen.
Iomegan hat geschrieben:Ich glaub ich bin zu doof hierfür :( Versuch das jetzt seit heute morgen.
Nicht aufgeben, das ist auch gar nicht einfach :)
Iomegan hat geschrieben:Hab inzwischen dies hier gefunden:
[...]
Da steige ich irgendwie besser durch :D
Diesen Code verstehst du?

Antworten