nicht Rucksack sondern Subset Sum

Neue Frage »

Auf diesen Beitrag antworten »
JROppenheimer nicht Rucksack sondern Subset Sum

Es geht um folgendes.

Gegeben sind eine Menge natürlicher Zahlen und ein Betrag.

Gefragt ist nach einem Algorithmus, der ausgibt, ob in der Menge Elemente sind, deren Summe den Betrag ergeben.

(ich hoffe ihr entschuldigt meine tipfaulheit)

Ich hab das jetzt versucht per dynamischer Programmierung zu implementieren, aber mal abgesehn vom IndexOutOfBounds, funktioniert es einfach nicht so, wie ich das gerne hätte. ... irgendwo hab ich einen Denkfehler ...

der code sieht so aus:

code:
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:
public static bool test(int betrag, int[] zahlen)
        {
            bool[] teilsumme = new bool[betrag];
            int[] benutzteElemente = new int[zahlen.GetLength(0)];
            teilsumme[0] = true;

            for (int i = 0; i < zahlen.GetLength(0); i++)
            {
                benutzteElemente[i] = 0;
            }
            for (int i = 0; i < betrag-1; i++)
            {
                teilsumme[i] = false;
            }
            for (int i = 1; i <= betrag; i++)
            {
                for (int j = 0; j <= zahlen.GetLength(0)-1; j++)
                {
                    System.Console.WriteLine("i=" + i + " j=" + j);
                    System.Console.ReadKey();
                    if (i+1 - zahlen[j] > 0)
                    {
                        if ((teilsumme[i - zahlen[j]] = true) & (benutzteElemente[j] == 0))
                        {
                            teilsumme[i] = true;
                            benutzteElemente[j] = 1;
                        }
                    }
                }
            }

                return teilsumme[betrag];   
        }



Ich bin nicht sicher wo mein Fehler ist.
 
Auf diesen Beitrag antworten »
JROppenheimer

Okay, da war ein kleines logisches problem. Die beiden Schleifen müssen genau anders herum geschachtelt werden, denn die elementare Erkentnis ist:

Ist eines der Elemente in der Summe zu B enthalten, dann ist es egal, WANN es dazu addiert wird, da Summen kommutativ sind!

Folglich betrachtet man jedes Element einmal und schaut, welche Summen (0...B)mit dem aktuell betrachteten Element erreichbar sind, diese ergeben sich aus den vorher betrachteten Elementen, und trägt für eben diese TRUE in die Tabelle ein und macht dann mit dem nächste Element weiter!
Der Code dazu sieht so aus:

code:
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:
public static bool test(int betrag, int[] zahlen)
        {
            int B = betrag;
            int n = zahlen.GetLength(0);

            //Nun das Array erstellen mit den Werten von 0..B, also mit B+1 Elementen
            bool[] teilsumme = new bool[B + 1];

            for (int i = 0; i <= B; i++)
            {
                teilsumme[i] = false;
            }

            //Die 0 ist ja trivial darstellbar
            teilsumme[0] = true;


            for (int i = 0; i < n; i++)
            {
                for (int b = B; b >= 0; b--) //von oben nach unten
                {
                    if (b - zahlen[i] >= 0)    //wichtig ist hier auch die überprüfung mit = 0
                    {
                        if (teilsumme[b - zahlen[i]])
                        {
                            teilsumme[b] = true;
                        }
                    }
                }
            }

            return teilsumme[betrag];
        }


Mit den freundlichsten Grüßen!
 
Neue Frage »
Antworten »


Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »