Optimalkan multiplikasi rantai matriks

9

Tantangan ini adalah untuk menghitung urutan penggandaan yang paling efisien untuk produk dari beberapa matriks.

Ukuran matriks ditentukan pada satu baris input standar. Anda harus mencetak ke output standar daftar bilangan bulat yang menunjukkan urutan untuk melakukan perkalian untuk meminimalkan total biaya perkalian.

Contoh 1

memasukkan

5x6 6x12 12x100 100x7

keluaran

3 2 1

Baris input akan menjadi daftar ukuran matriks yang dipisahkan oleh ruang, yang masing-masing adalah jumlah baris, diikuti oleh x, diikuti oleh jumlah kolom. Sebagai contoh, ada 4 matriks untuk dikalikan bersama (jadi 3 total perkalian), dan karena perkalian matriks adalah asosiatif mereka dapat dilakukan dalam urutan apa pun.

Keluaran harus berupa urutan untuk melakukan perkalian guna meminimalkan total biaya. Ini harus berupa daftar bilangan bulat yang dipisahkan spasi yang mewakili indeks perkalian untuk dilakukan selanjutnya. Untuk matriks N, daftar ini harus berisi angka 1 hingga N-1, inklusif. Misalnya 1, output 3 2 1berarti Anda harus melakukan 12x100 * 100x7perkalian terlebih dahulu, lalu 6x12 * 12x7perkalian (matriks kedua kali hasil dari langkah sebelumnya), kemudian akhirnya hasil 5x6 * 6x7perkalian.

Penggandaan matriks akan selalu kompatibel, yaitu jumlah kolom dari suatu matriks akan cocok dengan jumlah baris dari matriks berikutnya. Anggap biaya mengalikan dua matriks AxB * BxCadalah A*B*C.

Kode Anda harus menangani daftar hingga 100 matriks, masing-masing dimensi hingga 999, dan melakukannya dalam waktu yang wajar.

contoh 2

memasukkan

5x10 10x5 5x15 15x5

keluaran

1 3 2

atau

3 1 2

contoh 3

memasukkan

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

keluaran

2 3 4 5 6 7 8 1

Catatan: untuk verifikasi, total biaya terbaik untuk tiga contoh adalah 9114, 750, dan 1466344.

Kode terpendek menang!

Keith Randall
sumber
Apakah Anda yakin tentang contoh terakhir? Total biaya yang diberikan oleh kode saya adalah 1466344.
Howard
@ Howard: Ya, Anda benar, ada bug dalam kode saya. Tetap.
Keith Randall

Jawaban:

1

Ruby, 176 172 205 karakter

Ini adalah versi lain (beberapa karakter lebih lama) yang juga akan berjalan untuk input besar dalam waktu yang wajar.

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

Versi pertama: implementasi rekursif langsung di Ruby. Itu melakukan pencarian lengkap dan karenanya mungkin lambat pada input besar.

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
sumber
Bagian dari tantangannya adalah untuk menangani 100 matriks dalam waktu yang wajar, yang mana kode ini tidak.
Keith Randall
@KeithRandall Ah, saya tidak membaca kalimat itu (dan saya tidak suka - itu adalah pengekangan yang sangat kuat). Saya akan mencoba membangun solusi yang dapat menangani kasus ini juga.
Howard