切換
舊版
前往
大廳
主題

ZeroJudge - c112: 00348 - Optimal Array Multiplication Sequence 解題心得

Not In My Back Yard | 2019-05-05 23:57:33 | 巴幣 0 | 人氣 278

題目連結:


題目大意:
給定一正整數 N (N ≦ 10),代表有 N 個矩陣要相乘。接著有 N 列輸入,每列給定兩正整數。這 N 列分別代表第一個矩陣、第二個矩陣……(以下稱 A 、 A ……)有幾列(Rows)幾行(Columns)。

這 N 個矩陣相乘的結果即為 A × A × …… × A ,但是有可能因為運算順序不同而導致相乘時的乘法運算次數不同。例 A = 1 × 5 、 A = 5 × 10 、 A = 10 × 5(列數 × 行數),若先算 A × A 再乘以 A ,則用了 100 次的乘法運算;若是先求 A × A,左邊再乘以 A ,則用了 275 次乘法。

因此,本題目標是給定 N 個矩陣的行列值,求怎樣的運算順序可以使得運算次數最小化。將運算順序用括號表示出來。輸出格式參見範例輸出。



範例輸入:
3
1 5
5 20
20 1
3
5 10
10 20
20 35
6
30 35
35 15
15 5
5 10
10 20
20 25
0


範例輸出:
Case 1: (A1 x (A2 x A3))
Case 2: ((A1 x A2) x A3)
Case 3: ((A1 x (A2 x A3)) x ((A4 x A5) x A6))


解題思維:
定義兩個二維陣列,Di,j 以及 Pi,j ,分別代表第 i ~ j 個矩陣相乘所需最小的乘法運算次數和從哪兩個矩陣中間分割(先各自算左右兩邊,再合併)可以使得 i ~ j 的相乘運算次數最小。

則可得知:
其中 Di,k 之 k 代表窮舉 i ~ j 從何者分割(即 i ≦ k ≦ j)、R 代表第 i 個矩陣的列數、 C 代表第 k 個矩陣的行數。

因此,
我們可以像這樣子一步一步推出 D1, N 的值。先設定 D1, 1 、 D2, 2 …… DN, N 為零。再對於每個 i ~ i + 1 用上面遞迴式窮舉分割點 k 的方式求出 Di, i+1 。再用類似的方法窮舉 i ~ i + 2 的分割,得出 Di, i+2 ……以此類推。最後便可得出所求的 D1, N

以上是單純求最小的運算次數,而要求最佳的分割也可以用上面的方法。只要在窮舉分割的時候,只要窮舉出的 k 值造成比當前的解(當前的 Di, j)更小的次數,則Pi, j 便等於 k 。

最後要輸出最佳的運算順序的括號時,便是先輸出一個「(」,然後遞迴分割點(Pi, j)的左半邊(i~ Pi, j)。再輸出一個「x」,再遞迴右半邊(Pi, j ~ j),最後輸出一個「)」。而當遞迴的時候,若 i = j 時,則輸出「Ai」(此時要輸出i的值,而不是「i」),並回到上一層的遞迴堆疊。

然而,原題雖說輸出任意一組可行解就好(可能有多種解)。但是因為本題沒有特別判斷,因此要照其規則來找出題目要的可行解——當有一個陣列可分在左右兩邊而不影響結果時,就把它歸類在左半邊。因此窮舉 i 的時候,要由大至小窮舉。

此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作