Ottimizza la moltiplicazione della catena di matrici


9

Questa sfida consiste nel calcolare l' ordine di moltiplicazione più efficiente per un prodotto di più matrici.

La dimensione delle matrici è specificata su una singola riga di input standard. È necessario stampare sull'output standard un elenco di numeri interi che indica l'ordine in cui eseguire le moltiplicazioni per ridurre al minimo il costo totale delle moltiplicazioni.

Esempio 1

ingresso

5x6 6x12 12x100 100x7

produzione

3 2 1

La riga di input sarà un elenco separato da spazi di dimensioni matrice, ciascuna delle quali è il numero di righe, seguito da un x, seguito dal numero di colonne. Ad esempio, ci sono 4 matrici da moltiplicare insieme (quindi 3 moltiplicazioni totali) e poiché la moltiplicazione di matrici è associativa, possono essere eseguite in qualsiasi ordine.

L'output dovrebbe essere l'ordine in cui eseguire le moltiplicazioni per ridurre al minimo il costo totale. Questo dovrebbe essere un elenco separato da spazi di numeri interi che rappresentano l'indice della moltiplicazione da eseguire successivamente. Per le matrici N, questo elenco deve contenere i numeri da 1 a N-1, inclusi. Ad esempio 1, l'output 3 2 1indica che dovresti prima eseguire la 12x100 * 100x7moltiplicazione, quindi la 6x12 * 12x7moltiplicazione (la seconda matrice moltiplica il risultato del passaggio precedente), quindi infine la 5x6 * 6x7moltiplicazione risultante .

Le moltiplicazioni di matrice saranno sempre compatibili, ovvero il numero di colonne di una matrice corrisponderà al numero di righe della matrice successiva. Supponiamo che il costo della moltiplicazione di due matrici AxB * BxCsia A*B*C.

Il codice deve gestire elenchi di un massimo di 100 matrici, ciascuna delle dimensioni fino a 999, e farlo in un tempo ragionevole.

esempio 2

ingresso

5x10 10x5 5x15 15x5

produzione

1 3 2

o

3 1 2

esempio 3

ingresso

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

produzione

2 3 4 5 6 7 8 1

Nota: per la verifica, il miglior costo totale per i tre esempi è 9114, 750 e 1466344.

Vince il codice più corto!


Sei sicuro dell'ultimo esempio? Il costo totale indicato dal mio codice è 1466344.
Howard,

@Howard: Sì, hai ragione, un bug nel mio codice. Fisso.
Keith Randall,

Risposte:


1

Rubino, 176 172 205 caratteri

Ecco un'altra versione (più caratteri più lunghi) che verrà eseguita anche per input di grandi dimensioni in tempi ragionevoli.

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]*' '

Prima versione: implementazione diretta ricorsiva in Ruby. Fa una ricerca completa e quindi potrebbe essere lenta su input di grandi dimensioni.

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]*' '

Parte della sfida è gestire 100 matrici in un tempo ragionevole, cosa che questo codice non ha.
Keith Randall,

@KeithRandall Ah, non ho letto quella frase (e non mi piace - è un limite molto forte). Proverò a costruire una soluzione in grado di gestire anche questo caso.
Howard,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.