問題B:Y
制限時間:1秒 メモリ制限:256メガバイト
フェイス質問
彼は公に質問に直面して減少しました。
問題の解決策
双方向の検索を考えてみましょう。
$のcal_ {I、J、K} $はI、エンドポイントjの長さがあったか否かをサーチの現在の状態を表す定義され、状態側が状態kを探索します。
また、定義された状態設計の$ cal2_ {I、J、K} $。各配列の検索半分は、暴力を転送することができます。
初期化を考慮します。$ cal_ {I、J、K} $配列が始点ノード、$ cal_ {0,1,0} = 1 $の初期値でなければなりません。
そして$ cal2_ {I、J、K} $配列の任意の出発点。従って$ cal_ {0、iは、0} = 1 $(iが[1、N]で\します)。
最後に、状態の両半分を考える二つの状態が存在するかどうかを決定するために、最終状態である状態列挙ブレークポイントを構成する全電流状態に一緒にスプライスすることができます。
スプライシングの問題の方向については、あなたは少しそれを変更$ CAL2 $配列の状態を定義することができます。検索を逆に、現在のjのための出発点は、このような状態は、ステッチのCAL2ずに逆にすることができます。状態遷移変わりません。
$カルは、[21] [91] [(1 << 20)+10] $ ,:( なぜオープン検索には、開いていない場合、そう配列定義がされるのサイズ2003847846個の単語の状態、すなわち分離されません爆発的な成長の数。)
#include <ビット/ STDC ++ H> の#define RINTレジスタINT 使用して 名前空間STDを、 INTのN、M、D、ANS、LEN、REN。 BOOL CAL [ 23 ] [ 103 ] [ 20003 ]、CAL2 [ 23 ] [ 103 ] [ 20003 ]。 ベクター <ペア< 整数、整数 >> V [ 20003 ]。 INT メイン() { scanf関数(" %D%D%D "、&N、&M、&D)、LEN = D / 2、REN = D- LEN。 CAL [ 0 ] [ 1 ] [0 ] = 1 ; 用(RINT I = 1 ; I <= N; ++ I)CAL2 [ 0 ] [i]が[ 0 ] = 1 ; 用(RINT I = 1 ; I <= M ++、ST、EN、CL I) { scanf関数(" %D%D%D "、およびST&EN、&CL); V [ST] .push_back(make_pair(EN、CL))。 V [EN] .push_back(make_pair(ST、CL))。 } ため(RINT i = 0 ; iがLEN <; ++ I) のために(RINTのJ = 0 ; J <(1 << I); ++ j)の ための(RINTのK =1 ; = N <K; ++ 、K) であれば(CAL [I] [K] [J]) { 用(RINTのQ = 0 ; Q <V [k]は.size(); ++ Q) CAL [I + 1 ] [V [k]は[Q] 1次回] [(J << 1)+ V [k]は[Q] .second] = 1 。 } ため(RINT i = 0 ; iはRENを<; ++ I) のために(RINTのJ = 0 ; J <(1 << I); ++ j)の ための(RINTのK = 1 ; K <= N; ++ K) であれば(CAL2 [I] [K] [J]) { 用(RINTのQ =0 ; Q <V [k]は.size(); ++ Q) CAL2 [I + 1 ] [V [k]は[Q] 1次回] [(J << 1)+ V [k]は[Q]。第] = 1 。 } ため(RINT i = 0 ; iが(< 1 << D)を; ++ I)のために(RINTのJ = 1 ; J <= N; ++ j)の 場合(CAL [LEN] [j]は[I >> REN] && CAL2 [REN] [j]は[I&(1つの << REN) - 1 ]){ANS ++。ブレーク;} のprintf(" %d個の\ n " 、ANS)。 }