問題の説明 リンク
n個の行列{A1、A2、...、An}が与えられた場合、これらのn個の行列の連続積A1A2 ... Anを調べます。行列の乗算は組み合わせの法則を満たすため、行列の連続積を計算するための計算順序はさまざまです。
行列連続積の計算順序は、その計算量と密接に関連しています。たとえば、3つの行列{A1、A2、A3}の連続積を計算する例を考えてみます。これら3つの行列の次元をそれぞれ10 * 100、100 * 5、5 * 50とします。(A1A2)A3に従って計算された場合、3つの連続する行列の積に必要な乗算時間は10 * 100 * 5 + 10 * 5 * 50 = 7500です。A1(A2A3)に従って計算する場合、100 * 5 * 50 + 10 * 100 * 50 = 75000回必要です。
次に、特定の行列乗算スキームに必要な回数を計算します。
入力
入力データは、複数のデータセットで構成されています。各データグループの形式は次のとおりです。
最初の行は整数n(1≤n≤26)で、行列の数を示します。
次のn行では、各行にマトリックスの名前を示す大文字があり、その後にマトリックスの行と列の数をそれぞれ表す2つの整数a、bが続きます(1 <a、b <100)。
行n + 1は、括弧と大文字からなる行列乗算の式で、乗算記号と余分なスペースはありません。式に括弧がない場合は、左から右に計算され、入力された括弧は必ず一致します。
最初の行は整数n(1≤n≤26)で、行列の数を示します。
次のn行では、各行にマトリックスの名前を示す大文字があり、その後にマトリックスの行と列の数をそれぞれ表す2つの整数a、bが続きます(1 <a、b <100)。
行n + 1は、括弧と大文字からなる行列乗算の式で、乗算記号と余分なスペースはありません。式に括弧がない場合は、左から右に計算され、入力された括弧は必ず一致します。
出力
データの各セットについて、出力の1行のみに整数、つまり、行列乗算スキームに必要な回数が含まれます。演算中に行列の乗算規則が満たされない場合(つまり、左側の行列の列数が右側の行列の行数と異なる場合)、「エラー」が出力されます。
入力例
3 A 10100 B 100 5 C 5 50 A(BC)
出力例
75000
#include <iostream> #include < string > #include <deque> using namespace std; / * アイデア:STLの両端キューで実行し、2ラウンドで処理します。 最初のラウンド:最初に括弧の内部シーケンスを処理します。(())を重ね合わせるので、遭遇するたびに)シーケンスを 角かっこで見つけて計算し、結果をシーケンスに戻します。2番目のラウンド:角かっこが処理されるため、左で乗算 すると注意することができます:そうでない場合行列の行と列はジャンプアウトできます * / // Matrix struct Matrix { int row、lie; }; int main() { Matrix ms [ 28 ]; int n、row、lie; char name; string xl; // 入力シーケンスを 保存しますながら(CIN >> N-) { 一方(N-- ) { CIN >>名>>行リー; MS [名前 - ' A ' ] .Row = 行; MS [名前 - ' A ' ] = .lie リー; } GETCHAR(); // 取得シーケンス のgetline(CIN、XL); ロング ロング SUM = 0 ; 両端キュー < チャー > DQ; // 最初のフィルタホイールブラケット のための(int i = 0 ; i <xl.size(); i ++ ) { if(xl [i]!= ' )' ) { dq.push_back(xl [i]); } // 括弧が条件を満たしているため、 else { string s ; while(dq.back()!= ' (' ) { s + = dq.back(); dq.pop_back(); } dq.pop_back(); // (ABC)がキューにない場合は、 CBA //次に、ABC を乗算します(int j = s.size()-1 ; j> 0 ; j-- ) { int m1 = s [j]- ' A ' ; // 最初の行列 int m2 = s [j- 1 ]- ' A ' ; // 2番目のマトリックス if(ms [m1] .lie!= ms [m2] .row) { // マトリックスルールマークに適合しない sum = -1 ; break ; } sum+ = ms [m1] .row * ms [m1] .lie * ms [m2] .lie; // 新しい行列は2番目の行列に格納され、 ms [m2] .row = ms [m1] .row;を繰り返します。 } // 乗算された行列はシーケンスに戻されます dq.push_back(s [ 0 ]); if(sum ==- 1 ) break ; } } if(sum!= -1 ) { // 通常のシーケンス 文字列s; を処理します (dq.size()) { s + = dq.front(); dq.pop_front(); } for(int j = 0 ; j <s.size()- 1 ; j ++ ) { int m1 = s [j]- ' A ' ; int m2 = s [j + 1 ]- ' A ' ; if(ms [m1] .lie!= ms [m2] .row) { sum = -1 ; 休憩; } sum + = ms [m1] .row * ms [m1] .lie *ms [m2] .lie; ms [m2] .row = ms [m1] .row; } if(sum!=- 1 ) { cout << sum << endl; 続ける; } } cout << " error " << endl; } }