Fzu_1977
For the point that must be taken, there must be a plug at that point. For unnecessary points, ifDPWhen there is no plug at this point, you can either put two plug at this point to open up a new connected component, or do not put the plug, is equivalent to not going through this point.
In addition, since there can only be one review, and the last point of the loop is uncertain, you can record whether the current loop has been formed, in this way, if a loop is formed and a plug or a point must be followed, then this solution is naturally illegal.
# Include <stdio. h> # Include < String . H># Define Maxd 15 # Define Hash 30007 # Define Size 500010 Int N, m, maze [maxd] [maxd], CH [maxd], code [maxd], isend; Char B [maxd]; Struct Hashmap { Int Head [hash], next [size], size; Long Long State [size], F [size]; Void Init () {memset (Head, - 1 , Sizeof (Head); Size = 0 ;} Void Push ( Long Long St, Long Long Ans ){ Int I, H = sT %Hash; For (I = head [H]; I! =- 1 ; I = Next [I]) If (St = State [I]) {f [I] + = Ans; Return ;} State [size] = ST, F [size] = Ans; next [size] = Head [H]; head [H] = Size ++ ; }} HM [ 2 ]; Void Decode ( Int * Code, Int M, Long Long St ){ Int I; isend = ST & 7 ; For (I = m; I> = 0 ; I -- ) {St >>= 3 ; Code [I] = ST & 7 ;}} Long Long Encode ( Int * Code, Int M ){ Int I, CNT = 1 ; Long Long St = 0 ; Memset (CH, - 1 , Sizeof (CH); ch [ 0 ] = 0 ; For (I = 0 ; I <= m; I ++ ){ If (CH [Code [I] =- 1 ) CH [Code [I] = CNT ++ ; Code [I] =Ch [Code [I]; ST <= 3 ; ST | = Code [I];} St <= 3 ; ST | = Isend ;} Void Init (){ Int I, J; scanf ( " % D " , & N ,&M); memset (maze, 0 , Sizeof (Maze )); For (I = 1 ; I <= N; I ++ ) {Scanf ( " % S " , B + 1 ); For (J = 1 ; J <= m; j ++){ If (B [J] = ' O ' ) Maze [I] [J] = 2 ; Else If (B [J] = ' * ' ) Maze [I] [J] = 1 ;}}} Void Shift ( Int * Code, Int M ){ Int I; For (I = m; I> 0 ; I -- ) Code [I] = Code [I- 1 ]; Code [ 0 ] = 0 ;} Void Dpblock ( Int I, Int J, Int Cur ){ Int K; For (K = 0 ; K <HM [cur]. size; k ++ ) {Decode (Code, M, HM [cur]. State [k]); Code [J - 1 ] = Code [J] = 0 ; If (J = M) shift (Code, m); HM [cur ^ 1 ]. Push (encode (Code, m), HM [cur]. f [k]);} Void Dpblank ( Int I, Int J, Int Cur ){ Int K, T, left, up; For (K = 0 ; K <HM [cur]. size; k ++) {Decode (Code, M, HM [cur]. State [k]); left = Code [J- 1 ], Up = Code [J]; If (Isend ){ If (Left | up | maze [I] [J] = 2 ) Continue ; Code [J - 1 ] = Code [J] = 0 ; If (J = M) shift (Code, m); HM [cur ^ 1 ]. Push (encode (Code, m), HM [cur]. f [k]); Continue ;} If (Left && Up ){ If (Left = Up) {code [J - 1 ] = Code [J] = 0 , Isend =1 ; If (J = M) shift (Code, m); HM [cur ^ 1 ]. Push (encode (Code, m), HM [cur]. f [k]);} Else {Code [J - 1 ] = Code [J] = 0 ; For (T = 0 ; T <= m; t ++ ) If (Code [T] = Up) Code [T] = Left; If (J = M) shift (Code, m); HM [cur ^ 1 ]. Push (encode (Code, m), HM [cur]. f [k]);} Else If (Left | Up ){ If (Maze [I] [J + 1 ]) {Code [J - 1 ] = 0 , Code [J] = left + Up; HM [cur ^ 1 ]. Push (encode (Code, m), HM [cur]. f [k]);} If (Maze [I + 1 ] [J]) {code [J - 1 ] = Left + up, code [J] = 0 ; If (J = M) shift (Code, m); HM [cur ^ 1 ]. Push (encode (Code, m), HM [cur]. f [k]);} Else { If (Maze [I + 1 ] [J] & maze [I] [J + 1 ]) {Code [J - 1 ] = Code [J] =13 ; HM [cur ^ 1 ]. Push (encode (Code, m), HM [cur]. f [k]);} If (Maze [I] [J] = 1 ) {Code [J - 1 ] = Code [J] = 0 ; If (J = M) shift (Code, m); HM [cur ^1 ]. Push (encode (Code, m), HM [cur]. f [k]) ;}}} Void Solve (){ Int I, j, cur = 0 ; Long Long Ans = 0 ; HM [cur]. INIT (); HM [cur]. Push ( 0 , 1 ); For (I = 1 ; I <= N; I ++ ) For (J = 1 ; J <= m; j ++ ) {HM [cur ^ 1 ]. INIT (); If (Maze [I] [J] = 0 ) Dpblock (I, j, cur ); Else Dpblank (I, j, cur); cur ^ =1 ;} For (I = 0 ; I <HM [cur]. size; I ++ ) Ans + = HM [cur]. f [I]; printf ( " % I64d \ n " , ANS );} Int Main (){ Int T, TT; scanf ( " % D " ,& T ); For (Tt = 0 ; TT <t; TT ++ ) {Init (); printf ( " Case % d: " , Tt + 1 ); Solve ();} Return 0 ;}