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を返します。 }