Оптимізуйте множення матричного ланцюга


9

Ця задача полягає в обчисленні найбільш ефективного порядку множення для добутку з кількох матриць.

Розмір матриць задається в одному рядку стандартного вводу. Ви повинні надрукувати на стандартному виході список цілих чисел із зазначенням порядку, в якому потрібно робити множення, щоб мінімізувати загальну вартість множення.

приклад 1

вхід

5x6 6x12 12x100 100x7

вихід

3 2 1

Рядок введення буде розділеним пробілом списком розмірів матриць, кожний з яких - це кількість рядків, а за ними - an x, а потім число стовпців. Наприклад, є 4 матриці для множення разом (тобто 3 загальних множення), а оскільки множення матриць є асоціативним, їх можна зробити в будь-якому порядку.

Вихід повинен мати порядок виконання множень, щоб мінімізувати загальну вартість. Це повинен бути розділений пробілом список цілих чисел, що представляють індекс множення, який слід виконати далі. Для N матриць цей список повинен містити числа від 1 до N-1 включно. Наприклад, 1, вихід 3 2 1означає, що ви повинні зробити 12x100 * 100x7множення спочатку, потім 6x12 * 12x7множення (друга матриця кратна результату попереднього кроку), а потім нарешті 5x6 * 6x7множення.

Множення матриці завжди буде сумісним, тобто кількість стовпців матриці буде відповідати кількості рядків наступної матриці. Припустимо, вартість множення двох матриць AxB * BxCє A*B*C.

Ваш код повинен обробляти списки до 100 матриць, кожна з розмірів до 999, і робити це в розумний час.

приклад 2

вхід

5x10 10x5 5x15 15x5

вихід

1 3 2

або

3 1 2

приклад 3

вхід

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

вихід

2 3 4 5 6 7 8 1

Примітка. Для перевірки найкраща загальна вартість для трьох прикладів - 9114, 750 та 1466344.

Найкоротший код виграє!


Ви впевнені в останньому прикладі? Загальна вартість, подана за моїм кодом, - 1466344.
Говард,

@Howard: Так, ти маєш рацію, помилка в моєму коді. Виправлено.
Кіт Рендалл

Відповіді:


1

Рубі, 176 172 205 символів

Ось ще одна версія (на кілька символів довше), яка також працюватиме за великий внесок у розумний час.

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

Перша версія: пряма рекурсивна реалізація в Ruby. Він здійснює повний пошук і, таким чином, може бути повільним на великих входах.

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

Частина завдання полягає в тому, щоб обробити 100 матриць у розумний час, чого цей код не відповідає.
Кіт Рендалл

@KeithRandall Ах, я не прочитав це речення (і мені це не подобається - це дуже сильна стриманість). Я спробую створити рішення, яке також може впоратися з цією справою.
Говард
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.