FZU1061

 問題の説明   リンク

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は、括弧と大文字からなる行列乗算の式で、乗算記号と余分なスペースはありません。式に括弧がない場合は、左から右に計算され、入力された括弧は必ず一致します。

 出力

データの各セットについて、出力の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(); 
            } 
            forint 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; 
    } 
}

 

おすすめ

転載: www.cnblogs.com/dlvguo/p/12680238.html