pku1736 恶心的插头DP,终于被搞定了。括号匹配法+hash+四进制

pku1736 恶心的插头DP,终于被搞定了。括号匹配法+hash+四进制

一个网格图上某些格子是不能到达了,求从左下角到右下角哈密顿路的数量。
研究了大牛的论文好久,终于写出了这道题目
首先将哈密顿路径改造成哈密顿回路,这样就可以用联通性DP来求得路径数量。
大概方法间论文 http://www.cppblog.com/Files/yzhw/dp.doc
下面我说点细节部分
首先是行末的转移,最后一个轮廓线不能有右插头,并且需要将状态右移
举例来说
假设行末的状态为()..().,竖着的轮廓线在最后一个格子的右侧
下行第一个格子的状态即为.()..(),竖着的轮廓线在第一个格子的左侧
自认为java跑了500ms还算快的了~
  1  import  java.util. * ;
  2  import  java.util.Map.Entry;
  3  import  java.io. * ;
  4  public   class  Main {
  5 
  6       /**
  7       *  @param  args
  8        */
  9       static   int  r = 0 ,c = 0 ;
 10       static  String map[] = new  String[ 10 ];
 11       static  HashMap < Integer,Integer >  dp[][] = new  HashMap[ 10 ][ 2 ];
 12       static   final   int  encode( int  code[])
 13      {
 14           int  res = 0 ;
 15           for ( int  i = 0 ;i < code.length;i ++ )
 16          {
 17              res <<= 2 ;
 18              res |= code[i];
 19          }
 20           return  res;
 21      }
 22       static   final   void  decode( int  code[], int  cd)
 23      {
 24           for ( int  i = code.length - 1 ;i >= 0 ;i -- )
 25          {
 26              code[i] = cd & 3 ;
 27              cd >>= 2 ;
 28          }
 29      }
 30       static   void  print( int  i, int  j, int  code[], int  num)
 31      {
 32       /*     System.out.print("row="+i+" col="+j+" code=");
 33          for(int k=0;k<code.length;k++)
 34              System.out.print(code[k]+" ");
 35          System.out.println(num); */
 36      }
 37       public   static   void  main(String[] args)  throws  IOException{
 38          BufferedReader in = new  BufferedReader( new  InputStreamReader(System.in));
 39           for ( int  i = 0 ;i < 10 ;i ++ )
 40               for ( int  j = 0 ;j < 2 ;j ++ )
 41                  dp[i][j] = new  HashMap < Integer,Integer > ();
 42           while ( true )
 43          {
 44              String tmp[] = in.readLine().split( "   " );
 45              r = Integer.parseInt(tmp[ 0 ]);
 46              c = Integer.parseInt(tmp[ 1 ]);
 47               if (r == 0 && c == 0 break ;
 48              map[ 0 ] = "" ;
 49               for ( int  i = 0 ;i < c + 4 ;i ++ )
 50                  map[ 0 ] += ' . ' ;
 51              map[ 1 ] = " . " ;
 52               for ( int  i = 0 ;i < c + 2 ;i ++ )
 53                  map[ 1 ] += ' # ' ;
 54              map[ 1 ] += ' . ' ;
 55               for ( int  i = 2 ;i < 2 + r;i ++ )
 56              {
 57                  map[i] = in.readLine();
 58                   if (i != 1 + r) map[i] = " .# " + map[i] + " #. " ;
 59                   else  map[i] = " .. " + map[i] + " .. " ;
 60              }
 61              c += 4 ;
 62              r += 2 ;
 63               int  last = 0 ;
 64           //     for(int i=0;i<r;i++)
 65           //         System.out.println(map[i]);
 66           //     System.out.println();
 67              dp[ 0 ][ 0 ].clear();
 68               int  code[] = new   int [r + 1 ];
 69              code[ 0 ] = 1 ;
 70              code[ 1 ] = 2 ;
 71              dp[ 0 ][ 0 ].put(encode(code),  1 );
 72               for ( int  j = 0 ;j < c;j ++ )
 73                   for ( int  i = 0 ;i < r;i ++ )
 74                  {
 75                       if (i == 0 && j == 0 continue ;
 76                      dp[i][j & 1 ].clear();
 77                       int  p1 = (i == 0 ? r - 1 :i - 1 ),p2 = (i == 0 ? j - 1 :j);
 78                       for (Entry < Integer, Integer >  p:dp[p1][p2 & 1 ].entrySet())
 79                      {
 80                          decode(code,p.getKey());
 81                          print(p1,p2,code,p.getValue());
 82                           if (map[i].charAt(j) == ' . ' )
 83                          {
 84                              last = i * c + j;
 85                               if (i == r - 1 )
 86                              {
 87                                   if (code[i] == 2 && code[i + 1 ] == 1 || i == r - 1 && j == c - 1 && code[i] == 1 && code[i + 1 ] == 2 )
 88                                  {
 89                                      code[i] = 0 ;
 90                                      code[i + 1 ] = 0 ;
 91                                       if (dp[i][j & 1 ].containsKey(encode(code) >> 2 ))
 92                                          dp[i][j & 1 ].put(encode(code) >> 2 , dp[i][j & 1 ].get(encode(code) >> 2 ) + p.getValue());
 93                                       else
 94                                          dp[i][j & 1 ].put(encode(code) >> 2 , p.getValue());
 95                                  }
 96                                   else   if (code[i] == 0 && code[i + 1 ] != 0 || code[i + 1 ] == 0 && code[i] != 0 )
 97                                  {
 98                                      code[i] = (code[i] != 0 ? code[i]:code[i + 1 ]);
 99                                      code[i + 1 ] = 0 ;
100                                       if (dp[i][j & 1 ].containsKey(encode(code) >> 2 ))
101                                          dp[i][j & 1 ].put(encode(code) >> 2 , dp[i][j & 1 ].get(encode(code) >> 2 ) + p.getValue());
102                                       else
103                                          dp[i][j & 1 ].put(encode(code) >> 2 , p.getValue());
104                                  }
105                                   else   if (code[i] == 2 && code[i + 1 ] == 2 )
106                                  {
107                                       int  t = 0 ;
108                                      code[i] = code[i + 1 ] = 0 ;
109                                       for ( int  k = i - 1 ;k >= 0 ;k -- )
110                                      {
111                                           if (code[k] == 1 ) t ++ ;
112                                           else   if (code[k] == 2 ) t -- ;
113                                           if (t == 1 )
114                                          {
115                                              code[k] = 2 ;
116                                               break ;
117                                          }
118                                      }
119                                       if (dp[i][j & 1 ].containsKey(encode(code) >> 2 ))
120                                          dp[i][j & 1 ].put(encode(code) >> 2 , dp[i][j & 1 ].get(encode(code) >> 2 ) + p.getValue());
121                                       else
122                                          dp[i][j & 1 ].put(encode(code) >> 2 , p.getValue());
123                                  }
124                              }
125                               else
126                              {
127                                   if (code[i] == 0 && code[i + 1 ] == 0 )
128                                  {
129                                      code[i] = 1 ;
130                                      code[i + 1 ] = 2 ;
131                                       if (dp[i][j & 1 ].containsKey(encode(code)))
132                                          dp[i][j & 1 ].put(encode(code), dp[i][j & 1 ].get(encode(code)) + p.getValue());
133                                       else
134                                          dp[i][j & 1 ].put(encode(code), p.getValue());
135                                  }
136                                   else   if (code[i] == 2 && code[i + 1 ] == 1 || i == r - 1 && j == c - 1 && code[i] == 1 && code[i + 1 ] == 2 )
137                                  {
138                                      code[i] = code[i + 1 ] = 0 ;
139                                       if (dp[i][j & 1 ].containsKey(encode(code)))
140                                          dp[i][j & 1 ].put(encode(code), dp[i][j & 1 ].get(encode(code)) + p.getValue());
141                                       else
142                                          dp[i][j & 1 ].put(encode(code), p.getValue());
143                                  }
144                                   else   if (code[i] == 0 || code[i + 1 ] == 0 )
145                                  {
146                                       if (dp[i][j & 1 ].containsKey(encode(code)))
147                                          dp[i][j & 1 ].put(encode(code), dp[i][j & 1 ].get(encode(code)) + p.getValue());
148                                       else
149                                          dp[i][j & 1 ].put(encode(code), p.getValue());
150                                       int  t = code[i];
151                                      code[i] = code[i + 1 ];
152                                      code[i + 1 ] = t;
153                                       if (dp[i][j & 1 ].containsKey(encode(code)))
154                                          dp[i][j & 1 ].put(encode(code), dp[i][j & 1 ].get(encode(code)) + p.getValue());
155                                       else
156                                          dp[i][j & 1 ].put(encode(code), p.getValue());
157                                  }
158                                   else   if (code[i] == 1 && code[i + 1 ] == 1 )
159                                  {
160                                       int  t = 0 ;
161                                      code[i] = code[i + 1 ] = 0 ;
162                                       for ( int  k = i + 2 ;k < code.length;k ++ )
163                                      {
164                                           if (code[k] == 1 ) t ++ ;
165                                           else   if (code[k] == 2 ) t -- ;
166                                           if (t ==- 1 )
167                                          {
168                                              code[k] = 1 ;
169                                               break ;
170                                          }
171                                      }
172                                       if (dp[i][j & 1 ].containsKey(encode(code)))
173                                          dp[i][j & 1 ].put(encode(code), dp[i][j & 1 ].get(encode(code)) + p.getValue());
174                                       else
175                                          dp[i][j & 1 ].put(encode(code), p.getValue());
176                                  }
177                                   else   if (code[i] == 2 && code[i + 1 ] == 2 )
178                                  {
179                                       int  t = 0 ;
180                                      code[i] = code[i + 1 ] = 0 ;
181                                       for ( int  k = i - 1 ;k >= 0 ;k -- )
182                                      {
183                                           if (code[k] == 1 ) t ++ ;
184                                           else   if (code[k] == 2 ) t -- ;
185                                           if (t == 1 )
186                                          {
187                                              code[k] = 2 ;
188                                               break ;
189                                          }
190                                      }
191                                       if (dp[i][j & 1 ].containsKey(encode(code)))
192                                          dp[i][j & 1 ].put(encode(code), dp[i][j & 1 ].get(encode(code)) + p.getValue());
193                                       else
194                                          dp[i][j & 1 ].put(encode(code), p.getValue());
195                                  }
196                              }
197                          }
198                           else
199                          {    
200                               if (code[i] == 0 && code[i + 1 ] == 0 )
201                                 if (i == r - 1 )
202                                {
203                                     if (code[i] == 0 && code[i + 1 ] == 0 )
204                                         if (dp[i][j & 1 ].containsKey(p.getKey() >> 2 ))
205                                            dp[i][j & 1 ].put(p.getKey() >> 2 , dp[i][j & 1 ].get(p.getKey() >> 2 ) + p.getValue());
206                                         else
207                                            dp[i][j & 1 ].put(p.getKey() >> 2 , p.getValue());
208                                }
209                                 else
210                                {
211                                     if (code[i] == 0 && code[i + 1 ] == 0 )
212                                         if (dp[i][j & 1 ].containsKey(p.getKey()))
213                                            dp[i][j & 1 ].put(p.getKey(), dp[i][j & 1 ].get(p.getKey()) + p.getValue());
214                                         else
215                                            dp[i][j & 1 ].put(p.getKey(), p.getValue());
216                                }
217                          }
218                      }
219                  }
220               if (last == (r - 1 ) * c + c - 1 )
221                  System.out.println(dp[r - 1 ][(c - 1 ) & 1 ].containsKey( 0 ) ? dp[r - 1 ][(c - 1 ) & 1 ].get( 0 ): 0 );
222               else
223                  System.out.println( 0 );
224          }
225 
226      }
227 
228  }
229 


你可能感兴趣的:(pku1736 恶心的插头DP,终于被搞定了。括号匹配法+hash+四进制)