hdu 3338 Kakuro Extension

hdu 3338 Kakuro Extension

http://acm.hdu.edu.cn/showproblem.php?pid=3338
构图我也不废话了,有人说了怎么构
详见http://www.cnblogs.com/ylfdrib/archive/2010/08/15/1799903.html
我只贴代码,最好自己写, 懂了构图,完全可以看懂我的代码。
  1  // 算法实现:ISAP算法(邻接表实现)
  2  #include  < iostream >
  3  #include  < cstdio >
  4  #include  < cstring >
  5  #define  M 121
  6  using   namespace  std;
  7  const   int  maxn  =   13201 ;  
  8  const   int  maxm  =   200001 ;
  9 
 10  struct  Edge{
 11      
 12       int  flag;
 13       int  i, j;
 14  }ee[maxn];
 15 
 16  struct  node {
 17       // x起点,y终点,f容量,next是以x为起点的上一条边在g中的位置,op是反向边在g中的下标位置
 18       int  x, y, f, op, next;     
 19  }g[maxm  *   2 ];
 20 
 21  char  mat[ M ][ M ][  10  ];
 22  char  ans[ M ][ M ];
 23  int  a[ M ][ M ], va[ M ][ M ];
 24  int  c[ M ][ M ], vc[ M ][ M ];
 25  int  b[ M ][ M ];
 26  int  m, n, S, E, aid, ccc;
 27 
 28  // first[]存储的是以x为起点的最后一条边的在数组g中的下标
 29  // sumd[]用于记录表示标号为i的顶点数有多少个,用于间隙优化
 30  // now[]临时记录以x为起点的最后一条边在数组g中的下标
 31  int  first[maxn],now[maxn],sumd[maxn];   
 32  int  ncount;                                 // 代表结点的总数
 33  int  dis[maxn],fanhui[maxn],pre[maxn],tot;  // dis[]用于记录距离标号,pre[i]记录i的前驱在g[]中的位置,tot记录边的总数
 34 
 35  void  insert( int  x,  int  y,  int  c) {
 36 
 37      tot ++ ;                    // tot记录边的总数
 38      g[tot].x = x;
 39      g[tot].y = y;   
 40      g[tot].f = c;
 41      g[tot].op = tot + 1 ;         // 反向边在g中的下标位置
 42      g[tot].next = first[x];    // 记录以x为起点的上一条边在g中的下标位置
 43      first[x] = tot;            // 以x为起点的边的位置
 44      tot ++ ;           
 45       // 反向边
 46      g[tot].x = y;
 47      g[tot].y = x;
 48      g[tot].f = 0 ;              // 反向边的初始网络流为0
 49      g[tot].op = tot - 1 ;
 50      g[tot].next = first[y];
 51      first[y] = tot;   
 52  }
 53  // ISAP算法
 54  int  maxflow( int  src,  int  des) {
 55 
 56       int  i,flow,t,j,tempmin;    // i,j用于标识结点,t用于标识结点在g中的位置
 57       bool  flag;                 // 用于标识是否找到了允许路径
 58       int  sumFlow;             
 59      memset(dis, 0 , sizeof (dis));       // 初始化dis为0             
 60      memset(sumd, 0 , sizeof (sumd));
 61       for (i = 1 ;i <= ncount;i ++ )       
 62          now[i] = first[i];     
 63      sumd[ 0 ] = ncount;                  // 标号为0的结点有ncount个
 64      sumFlow = 0 ;                       // sumFlow记录最大流,初始化为0
 65      i = src;                           // i初始化为起点
 66      flow = 10000000 ;
 67       while (dis[src] < ncount)
 68      {
 69          fanhui[i] = flow;
 70          flag = false ;    
 71          t = now[i];
 72           while (t != 0 )            // 寻找允许路径
 73          {
 74              j = g[t].y;
 75               if ((g[t].f > 0 ) && (dis[j] + 1 == dis[i]))  // 允许弧 
 76              {
 77                  flag = true ;
 78                  pre[j] = t;
 79                  now[i] = t;
 80                   if (g[t].f < flow)           // 找到允许增量
 81                      flow = g[t].f;
 82                  i = j;
 83                   if (i == ncount)                  // 找到了允许路径
 84                  {
 85                      sumFlow += flow;
 86                       while (i != src)           // 修改残余网络
 87                      {
 88                          g[pre[i]].f -= flow;             // 正向边
 89                          g[g[pre[i]].op].f += flow;       // 反向边
 90                          i = g[pre[i]].x;
 91                      }
 92                      flow = 10000000 ;
 93                  }
 94                   break ;
 95              }
 96              t = g[t].next;
 97          }
 98           if (flag)
 99               continue ;
100           // 没有找到允许路径
101          tempmin = ncount - 1 ;
102          t = first[i];
103           while (t != 0 )
104          {
105               if ((g[t].f > 0 ) && (dis[g[t].y] < tempmin))
106              {
107                  tempmin = dis[g[t].y];
108                  now[i] = t;
109              }
110              t = g[t].next;
111          }
112          sumd[dis[i]] -- ;
113           if (sumd[dis[i]] == 0 break ;            // 间隙优化
114          dis[i] = tempmin + 1 ;                     // 此处别忘+1,因为d[i]=tempmin{d[j]+1|(i,j)在残留网络中}
115          sumd[dis[i]] ++ ;
116           if (i != src)
117          {
118              i = g[pre[i]].x;
119              flow = fanhui[i];
120          }
121      }
122       return  sumFlow;
123  }
124 
125  void  solve( int  i,  int  j) {
126      
127       char  str[ 10 ];
128      strcpy(str, mat[ i ][ j ]);
129      
130       if (str[  0  ]  !=   ' X '   &&  str[  6  ]  !=   ' X ' ) {
131          
132           int  k;
133          
134          c[ i ][ j ]  =  aid  ++ ;
135          vc[ i ][ j ]  =   0 ;
136           for (k  =   0 ; k  <   3 ++  k) {
137              
138               if (str[ k ]  >=   ' 0 '   &&  str[ k ]  <=   ' 9 ' ) {
139                  
140                  vc[ i ][ j ]  =  vc[ i ][ j ]  *   10   +  str[ k ]  -   ' 0 ' ;
141              }
142          }
143          
144          a[ i ][ j ]  =  aid  ++ ;
145          va[ i ][ j ]  =   0 ;
146           for (k  =   4 ;k  <   7 ++  k) {
147              
148               if (str[ k ]  >=   ' 0 '   &&  str[ k ]  <=   ' 9 ' ) {
149                  
150                  va[ i ][ j ]  =  va[ i ][ j ]  *   10   +  str[ k ]  -   ' 0 ' ;
151              }
152          }    
153      }
154       else   if (str[  0  ]  !=   ' X ' ) {
155          
156          vc[ i ][ j ]  =   0 ;
157           for ( int  k  =   0 ; k  <   3 ++  k) {
158              
159               if (str[ k ]  >=   ' 0 '   &&  str[ k ]  <=   ' 9 ' ) {
160                  
161                  vc[ i ][ j ]  =  vc[ i ][ j ]  *   10   +  str[ k ]  -   ' 0 ' ;
162              }
163          }
164          c[ i ][ j ]  =  aid  ++ ;
165      }
166       else  {
167          
168          va[ i ][ j ]  =   0 ;
169          a[ i ][ j ]  =  aid  ++ ;
170          
171           for ( int  k  =   4 ;k  <   7 ++  k) {
172              
173               if (str[ k ]  >=   ' 0 '   &&  str[ k ]  <=   ' 9 ' ) {
174                  
175                  va[ i ][ j ]  =  va[ i ][ j ]  *   10   +  str[ k ]  -   ' 0 ' ;
176              }
177          }    
178      }
179  }
180 
181 
182  void  print( int  p[][ 101 ]) {
183      
184       for ( int  i  =   1 ; i  <=  m;  ++  i) {
185          
186           for ( int  j  =   1 ; j  <=  n;  ++  j)
187              printf( " %3d " , p[ i ][ j ]);
188          cout  <<  endl;
189      }
190      cout  <<  endl;
191  }
192 
193  void  init() {
194      
195      aid  =   1 ;
196       char  str[ 10 ];
197       int  i, j;
198      
199       for (i  =   1 ; i  <=  m;  ++  i) {
200          
201           for (j  =   1 ; j  <=  n;  ++  j) {
202              
203              va[ i ][ j ]  =   - 1 // va,vc先不要赋值0,否则像我一样杯具30次
204              vc[ i ][ j ]  =   - 1 ;
205              a[ i ][ j ]  =   - 1 ;
206              b[ i ][ j ]  =   - 1 ;
207              c[ i ][ j ]  =   - 1 ;
208              
209              strcpy(str, mat[ i ][ j ]);
210              
211               if (str[  0  ]  !=   ' . ' ) {
212                  
213                  ans[ i ][ j ]  =   ' _ ' ;
214                   if (str[  0  ]  !=   ' X '   ||  str[  6  ]  !=   ' X ' )
215                      solve(i, j);
216              }
217               else  {
218                  
219                  b[ i ][ j ]  =  aid  ++ ;
220              }
221          }
222      }
223      
224       // print(va);
225       // print(vc);
226      
227       for (i  =   1 ; i  <=  m;  ++  i) {
228          
229           for (j  =   1 ; j  <=  n;  ++  j) {
230              
231               if (va[ i ][ j ]  !=   - 1 ) {
232                  
233                   int  csd  =   0 ;
234                   for ( int  k  =  j  +   1 ; k  <=  n  &&  mat[ i ][ k ][  0  ]  ==   ' . ' ++  k) {
235                      
236                      csd  ++ ;
237                  }
238                  va[ i ][ j ]  -=  csd;
239              }
240              
241               if (vc[ i ][ j ]  !=   - 1 ) {
242                  
243                   int  csd  =   0 ;
244                   for ( int  k  =  i  +   1 ; k  <=  m  &&  mat[ k ][ j ][  0  ]  ==   ' . ' ++  k) {
245                      
246                      csd  ++ ;
247                  }
248                  vc[ i ][ j ]  -=  csd;
249              }
250          }
251      }
252      
253       // print(va);
254       // print(vc);
255      
256       for (i  =   1 ; i  <=  m;  ++  i) {
257          
258           for (j  =   1 ; j  <=  n;  ++  j) {
259              
260               if (i  >   1 ) {
261                  
262                   if (vc[ i ][ j ]  ==   - 1   &&  vc[i  -   1 ][ j ]  !=   - 1 ) {
263                      
264                      c[ i ][ j ]  =  c[i  -   1 ][ j ];
265                      vc[ i ][ j ]  =  vc[i  -   1 ][ j ];
266                  }
267              }
268              
269               if (j  >   1 ) {
270                  
271                   if (va[ i ][ j ]  ==   - 1   &&  va[ i ][j  -   1 !=   - 1 ) {
272                      
273                      a[ i ][ j ]  =  a[ i ][j  -   1 ];
274                      va[ i ][ j ]  =  va[ i ][j  -   1 ];
275                  }
276              }
277          }
278           // cout << endl;
279      }
280      
281      ccc  =   0 ;
282      tot  =   0 ;
283      S  =  aid, E  =  aid  +   1 ;
284      ncount  =  E;
285 
286      memset(first,  0 sizeof (first));
287 
288      
289       // print(a);
290       // print(b);
291       // print(c);
292       // print(va);
293       // print(vc);
294      
295       // cout << aid << endl;
296  }
297 
298  void  printRes() {
299      
300       for ( int  i  =   1 ; i  <=  m;  ++  i) {
301          
302           for ( int  j  =   1 ; j  <  n;  ++  j) {
303              
304              printf( " %c  " , ans[ i ][ j ]);
305          }
306          printf( " %c\n " , ans[ i ][ j ]);
307      }
308  }
309 
310 
311  int  main() {
312      
313       int  i, j;
314       while (scanf( " %d %d " & m,  & n)  ==   2 ) {
315          
316           for (i  =   1 ;i  <=  m;  ++  i) {
317              
318               for (j  =   1 ; j  <=  n;  ++  j) {
319                  
320                  scanf( " %s " , mat[ i ][ j ]);
321              }
322          }
323          
324          init();
325          
326           bool  aa[ maxn ];
327           for (i  =   1 ; i  <=  ncount;  ++  i)
328          aa[ i ]  =   false ;
329          
330          
331           for (i  =   1 ;i  <=  m;  ++  i) {
332              
333               for (j  =   1 ; j  <=  n;  ++  j) {
334                  
335                   if (b[ i ][ j ]  !=   - 1 ) {
336                      
337                       if ( ! aa[a[i][j]]) {
338                          
339                          insert(S, a[i][j], va[i][j]);
340                          aa[a[i][j]]  =   true ;
341                      }
342                      
343                      insert(a[i][j], b[i][j],  8 );
344 
345                      ee[ccc].flag  =  tot;
346                      ee[ccc].i  =  i;
347                      ee[ccc].j  =  j;
348                      ccc  ++ ;
349                      
350                      insert(b[i][j], c[i][j],  8 );
351                      
352                       if ( ! aa[c[i][j]]) {
353                          
354                          insert(c[i][j], E, vc[i][j]);
355                          aa[c[i][j]]  =   true ;
356                      }
357                  }
358              }
359          }
360          
361          maxflow(S, E);
362          
363           for (i  =   0 ; i  <  ccc ;  ++  i) {
364              
365               int  val  =  g[ee[ i ].flag].f;
366               int  loci  =  ee[ i ].i;
367               int  locj  =  ee[ i ].j;
368              
369              ans[ loci ][ locj ]  =  val  +   ' 1 '
370          }
371          
372          printRes();    
373      }
374       return   0 ;
375  }
376 


你可能感兴趣的:(hdu 3338 Kakuro Extension)