Optimieren Sie die Multiplikation der Matrixkette

9

Diese Herausforderung besteht darin, die effizienteste Multiplikationsreihenfolge für ein Produkt aus mehreren Matrizen zu berechnen .

Die Größe der Matrizen wird in einer einzelnen Zeile der Standardeingabe angegeben. Sie sollten eine Liste von Ganzzahlen in der Standardausgabe drucken, die die Reihenfolge angibt, in der die Multiplikationen durchgeführt werden sollen, um die Gesamtkosten für die Multiplikation zu minimieren.

Beispiel 1

Eingang

5x6 6x12 12x100 100x7

Ausgabe

3 2 1

Die Eingabezeile ist eine durch Leerzeichen getrennte Liste von Matrixgrößen, von denen jede die Anzahl der Zeilen ist, gefolgt von einer x, gefolgt von der Anzahl der Spalten. Für das Beispiel gibt es 4 Matrizen, die miteinander multipliziert werden müssen (also 3 Gesamtmultiplikationen), und da die Matrixmultiplikation assoziativ ist, können sie in beliebiger Reihenfolge durchgeführt werden.

Die Ausgabe sollte die Reihenfolge sein, in der die Multiplikationen durchgeführt werden, um die Gesamtkosten zu minimieren. Dies sollte eine durch Leerzeichen getrennte Liste von Ganzzahlen sein, die den Index der Multiplikation darstellen, die als nächstes ausgeführt werden soll. Für N Matrizen sollte diese Liste die Nummern 1 bis einschließlich N-1 enthalten. In Beispiel 1 3 2 1bedeutet die Ausgabe, dass Sie 12x100 * 100x7zuerst die 6x12 * 12x7Multiplikation durchführen sollten , dann die Multiplikation (die zweite Matrix multipliziert mit dem Ergebnis des vorherigen Schritts) und schließlich die resultierende 5x6 * 6x7Multiplikation.

Die Matrixmultiplikationen sind immer kompatibel, dh die Anzahl der Spalten einer Matrix stimmt mit der Anzahl der Zeilen der nachfolgenden Matrix überein. Angenommen , die Kosten für die Multiplikation zweier Matrizen AxB * BxCist A*B*C.

Ihr Code muss Listen mit bis zu 100 Matrizen mit einer Dimension von jeweils bis zu 999 verarbeiten und dies in angemessener Zeit.

Beispiel 2

Eingang

5x10 10x5 5x15 15x5

Ausgabe

1 3 2

oder

3 1 2

Beispiel 3

Eingang

22x11 11x78 78x123 123x666 666x35 35x97 97x111 111x20 20x50

Ausgabe

2 3 4 5 6 7 8 1

Hinweis: Zur Überprüfung betragen die besten Gesamtkosten für die drei Beispiele 9114, 750 und 1466344.

Der kürzeste Code gewinnt!

Keith Randall
quelle
Sind Sie sich über das letzte Beispiel sicher? Die Gesamtkosten, die durch meinen Code angegeben werden, sind 1466344.
Howard
@ Howard: Ja, du hast recht, ein Fehler in meinem Code. Fest.
Keith Randall

Antworten:

1

Ruby, 176 172 205 Zeichen

Hier ist eine andere Version (mehrere Zeichen länger), die in angemessener Zeit auch für große Eingaben ausgeführt wird.

q=(gets.split<<$_[/\d+$/]).map &:to_i
r=Hash.new{|h,i|h[i]=Hash.new{|h,j|h[j]=1e12;h[j]=i==j ?[0,[]]:(i...j).map{|k|a,c=r[i][k];b,d=r[k+1][j];[a+b+q[i-1]*q[k]*q[j],c+d+[k]]}.min}}
$><<r[1][q.size-1][1]*' '

Erste Version: gerade rekursive Implementierung in Ruby. Es führt eine vollständige Suche durch und kann daher bei großen Eingaben langsam sein.

k=->m{m[2]?(1..m.size-2).map{|l|s=k[m[0,l]+m[l+1..-1]];[m[l-1]*m[l]*m[l+1]+s[0],[l]+s[1].map{|u|u<l ?u:u+1}]}.min: [0,[]]}
$><<k[(gets.split<<$_[/\d+$/]).map &:to_i][1]*' '
Howard
quelle
Ein Teil der Herausforderung besteht darin, 100 Matrizen in einer angemessenen Zeit zu verarbeiten, was dieser Code nicht tut.
Keith Randall
@KeithRandall Ah, ich habe diesen Satz nicht gelesen (und ich mag ihn nicht - es ist eine sehr starke Zurückhaltung). Ich werde versuchen, eine Lösung zu entwickeln, die auch diesen Fall behandelt.
Howard