codeforces1202Bあなたは十進文字列...メモリ検索やフロイドの最短経路アルゴリズムを与えられています

URL:http://codeforces.com/problemset/problem/1202/B

質問の意味:

、かなりの周りに本当にある(中日バイリンガル)草は、シーケンスの束を与えることです、そして、あなたがそのような配列の数を記入し、それを埋めることができますこの質問は$のxy $カウンタの出力の番号の後に充填することができます。$ 0 $最初に、各ステッププラスプラス$の$ X $または$ Y、次いでモジュロ$に$ 10の数を出力:$ $ XYワークカウンタです。出力$ 0出力は$ $ -1を満たすことができない場合は、<$ $ XYカウンタの$ 10追加するために必要な文字の<X、Y最小数。

ソリューション:

草、検索の思い出を書き、オンラインでの情報のためのステップ法バイステップの試合は、正の解は、最短パスに変換されると思います。

メモリ検索DFS、

連続した配列$ 10 $モジュロための図と同じになるときに検索の層の数は、元の層の保全よりも小さい場合、したがって、$ DFS $のみ$ 10 $ラウンド遭遇するまで、数字を複製、$ 10 $ホイールを超えません番号は、以上の更新は、検索結果の層の最小数が返されることを保証します。そして、次の状態遷移に対応する文字の文字列、直読の状態を保存することができます。

ACコード:$(600msの)$

#include <ビット/ STDC ++ H> 
名前空間STDを使用して、
INT DP [15] [15] [15]、RES [15] [15]。
文字列str [2000005]。
INT X、Y。
ボイドDFS(INTのDIV、BOOLモード、int型CUR)
{ 
    (!モード)であれば
    { 
        CUR =(CUR + X)10%。
        IF(DP [X] [Y] [CUR] = - 1!)
            IF(DIV> = DP [X] [Y] [CUR])
                のリターン; 
        DP [X] [Y] [CUR] =のDIV。
        DFS(DIV + 1,0、CUR)。
        DFS(DIV + 1,1、CUR)。
    } 
    { 
        CURは=(CUR + Y)10%; 
        IF(DP [X] [Y] [CUR] = - 1!)
            IF(DIV> = DP [X] [Y] [CUR])
                のリターン; 
        DP [X] [Y] [CUR] =のDIV。
        DFS(DIV + 1,0、CUR)。
        DFS(DIV + 1,1、CUR)。
    } 
} 
ボイドのinit()
{ 
    memsetの(DP、-1、はsizeof(DP))。
    以下のために(INT i = 0; ++ I; 10 iは<)
        のための(int型J = 0; jは<10; ++ j)を
        { 
            Xが= iは、yはjは=。
            DFS(0,0,0)。
            DFS(0,1,0)。
        } 
} 
int型CAL(int型のx、int型のY、INT LEN)
{ 
    IF(LEN == 1)
        戻り0; 
    int型ANS = 0; 
    (; iがLEN <++ iはi = 1 INT)用
    { 
        INT TMP。
        INT DIS = STR [I] -str [I-1]; 
        一方、(DIS <0)
            DIS + = 10。
        TMP = DP [X] [Y] [DIS]。
        IF(TMP == - 1)
            リターン-1。 
            ANS + = TMP。
    } 
    戻りANS。
} 
int型のmain()
{ 
    INIT()。
    scanf関数( "%sの"、STR)。
    INT LEN = STRLEN(STR)。
    (; iが10 <++ iが0 = INT)のため
        のために(INT J = 0; J <10; ++ j)は
            RES [I] [J] = CAL(I、J、LEN)。
    以下のために(INT i = 0; iは<10; ++ I)
        のために(int型J = 0であり、j <10; ++ j)の
            printf関数( "%d個の%のC"、RES [I] [J](J = = 9 '\ n'は?:」「)); 
    0を返します。
}

 二、フロイドのアルゴリズム

状態遷移$ X-> Y $は$有向エッジの右側の$ X $ $ $ Yに$ 1を確立することと等価である、最小値に対応する$列strである[I-1] - > STR [i]は、(0 <私がlen <(STR))$最短経路ので、再実行の各場合について、図隣接行列メモリ直接構築はフロイドに$アルゴリズム$。

ACコード:$(200ミリ秒)$

#include <ビット/ STDC ++ H> 
名前空間STDを使用して、
INT DP [15] [15]、LEN。
文字列str [2000005]。
const int型INF = 0x3f3f3f3f。
INT解く(int型のx、int型のY)
{ 
    memsetの(DP、INF、はsizeof(DP))。
    (; iが10 <++ iが0 = INT)のために
        、DP [I] [(iはX + 1)10%] = DP [I] [(iはY + 1)10%] = 1。
    用(int型のk = 0; K <10; ++ K)
        のための(INT i = 0; iは<10; ++ I)
            のために(int型J = 0であり、j <10; ++ j)は
                DP [I] [ J] =分(DP [I]、[J]、DP [I] [K] + DP [K] [J])。
    int型ANS = 0; 
    以下のために(; iはi = 1 int型<LEN; ++ I)
    { 
        IF(DP [STR [I-1] - '0'] [STR [I] - '0']> = INF)
            リターン-1。
        ANS + = DP [STR [I-1] - '0'] [STR [I] - '0'] - 1。
INTメイン()
{ 
    scanf関数( "%sの"、STR)。
    LEN =(STR)strlenを。
    以下のために(++ I; iは10 <I = 0 INT)
        のための(int型J = 0であり、j <10; ++ j)の
            printf関数( "%d個の%のC"、解決(i、j)は、(jは== 9 '\ n'は?:」「)); 
    0を返します。
}

 

おすすめ

転載: www.cnblogs.com/Aya-Uchida/p/11330649.html