Optimizar la multiplicación de la cadena matricial

9

Este desafío es calcular el orden de multiplicación más eficiente para un producto de varias matrices.

El tamaño de las matrices se especifica en una sola línea de entrada estándar. Debe imprimir en la salida estándar una lista de enteros que indique el orden en que se realizan las multiplicaciones para minimizar el costo total de la multiplicación.

Ejemplo 1

entrada

5x6 6x12 12x100 100x7

salida

3 2 1

La línea de entrada será una lista de tamaños de matriz separados por espacios, cada uno de los cuales es el número de filas, seguido de un x, seguido del número de columnas. Para el ejemplo, hay 4 matrices para multiplicar juntas (es decir, 3 multiplicaciones totales), y dado que la multiplicación de matrices es asociativa, se pueden hacer en cualquier orden.

El resultado debe ser el orden en el que se realizan las multiplicaciones para minimizar el costo total. Esta debería ser una lista de enteros separados por espacios que representan el índice de la multiplicación que se realizará a continuación. Para N matrices, esta lista debe contener los números del 1 al N-1, inclusive. Por ejemplo 1, la salida 3 2 1significa que 12x100 * 100x7primero debe hacer la multiplicación, luego la 6x12 * 12x7multiplicación (la segunda matriz multiplicada por el resultado del paso anterior), y finalmente la 5x6 * 6x7multiplicación resultante .

Las multiplicaciones de la matriz siempre serán compatibles, es decir, el número de columnas de una matriz coincidirá con el número de filas de la matriz posterior. Suponga que el costo de multiplicar dos matrices AxB * BxCes A*B*C.

Su código debe manejar listas de hasta 100 matrices, cada una de dimensiones de hasta 999, y hacerlo en un tiempo razonable.

ejemplo 2

entrada

5x10 10x5 5x15 15x5

salida

1 3 2

o

3 1 2

ejemplo 3

entrada

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

salida

2 3 4 5 6 7 8 1

Nota: para la verificación, el mejor costo total para los tres ejemplos es 9114, 750 y 1466344.

¡El código más corto gana!

Keith Randall
fuente
¿Estás seguro del último ejemplo? El costo total dado por mi código es 1466344.
Howard
@Howard: Sí, tienes razón, un error en mi código. Fijo.
Keith Randall

Respuestas:

1

Ruby, 176 172 205 caracteres

Aquí hay otra versión (varios caracteres más largos) que también se ejecutará para una gran entrada en un tiempo razonable.

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

Primera versión: implementación recursiva directa en Ruby. Realiza una búsqueda completa y, por lo tanto, puede ser lento en entradas grandes.

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
fuente
Parte del desafío es manejar 100 matrices en un tiempo razonable, lo que no hace este código.
Keith Randall
@KeithRandall Ah, no leí esa oración (y no me gusta, es una restricción muy fuerte). Intentaré construir una solución que también pueda manejar este caso.
Howard