PKU 1077 Eight (续)

PKU 1077 Eight (续)

                                              A*算法解题

参考:
http://www.cppblog.com/longzxr/archive/2009/08/12/92978.html
http://www.chhaya.me/?p=182

第一次写A*,写的相当地繁琐,一方面是由于自己写了优先级队列,另一方面则是由于需要保存的信息相对较多,每个状态在队列中的位置都随着pop与push动态变化,所以新添了idx[]数组来存储当前的位置,数组下标是hash值

代码:
  1  #include < stdio.h >
  2  #include < stdlib.h >
  3  #include < string .h >
  4  #define  STR_LEN 9
  5  #define  HASH_LEN 362880 /* 9! */
  6  const   int  facs[]  =  { 1 2 6 24 120 720 5040 40320 };
  7  const   char  letters[]  =   " udlr " ;
  8  const   int  pos[]  =  { - 3 3 - 1 1 };  /*  up, down, left, right  */
  9  const   int  movable[][ 4 =  { 0 , 1 , 0 , 1 0 , 1 , 1 , 1 0 , 1 , 1 , 0 1 , 1 , 0 , 1 1 , 1 , 1 , 1 1 , 1 , 1 , 0 1 , 0 , 0 , 1 1 , 0 , 1 , 1 1 , 0 , 1 , 0 };
 10  const   int  points[][ 2 =  {{ 0 , 0 }, { 1 , 0 }, { 2 , 0 }, { 0 , - 1 }, { 1 , - 1 }, { 2 , - 1 }, { 0 , - 2 }, { 1 , - 2 }, { 2 , - 2 }};
 11  int  distance[STR_LEN][STR_LEN];
 12  struct  EACH {
 13       char  str[STR_LEN + 1 ];
 14       int  pos, value;
 15  } queue[HASH_LEN];
 16  int  pre[HASH_LEN], dir[HASH_LEN], g[HASH_LEN], h[HASH_LEN], idx[HASH_LEN];
 17  int  mark[HASH_LEN];  /*  0: unvisited / 1: open-list / 2: closed-list  */
 18  int  target;  /*  target hash value: "123456780"  */
 19 
 20  /*  ------begin: priority queue ------ */
 21  int  count;
 22  #define  LEFT_CLD(i) ((i<<1)+1)
 23  #define  RIGHT_CLD(i) ((i+1)<<1)
 24  #define  PARENT(i) ((i-1)>>1)
 25 
 26  int
 27  compare_item( struct  EACH  * arg1,  struct  EACH  * arg2)
 28  {
 29       return  ((g[arg1 -> value]  +  h[arg1 -> value])  -  (g[arg2 -> value]  +  h[arg2 -> value]));
 30  }
 31 
 32  void
 33  swap(i, j)
 34  {
 35       struct  EACH tmp  =  queue[i];
 36      queue[i]  =  queue[j];
 37      queue[j]  =  tmp;
 38      idx[queue[i].value]  =  j;
 39      idx[queue[j].value]  =  i;
 40  }
 41 
 42  void
 43  min_heapify( int  heapsize,  int  i)
 44  {
 45       int  min  =  i;
 46       int  left  =  LEFT_CLD(i);
 47       int  right  =  RIGHT_CLD(i);
 48       if (left < heapsize  &&  compare_item(queue + min, queue + left) > 0 )
 49          min  =  left;
 50       if (right < heapsize  &&  compare_item(queue + min, queue + right) > 0 )
 51          min  =  right;
 52       if (min  !=  i) {
 53          swap(i, min);
 54          min_heapify(heapsize, min);
 55      }
 56  }
 57 
 58  struct  EACH
 59  pop()
 60  {
 61       struct  EACH rt  =  queue[ 0 ];
 62      swap( 0 , count - 1 );
 63       -- count;
 64      min_heapify(count,  0 );
 65       return  rt;
 66  }
 67 
 68  void
 69  up_heapify( int  from)
 70  {
 71       int  cld, pt;
 72      cld  =  from;
 73      pt  =  PARENT(cld);
 74       while (cld > 0   &&  compare_item(queue + cld, queue + pt) < 0 ) {
 75          swap(cld, pt);
 76          cld  =  pt;
 77          pt  =  PARENT(cld);
 78      }
 79  }
 80 
 81  void
 82  push( struct  EACH item)
 83  {
 84       int  cld, pt;
 85       ++ count;
 86      queue[count - 1 =  item;
 87      up_heapify(count - 1 );
 88  }
 89  /*  -------end: priority queue ------- */
 90 
 91  /*  permutation -> number  */
 92  int  
 93  hash_func( char   * str)
 94  {
 95       int  i, j, cnt, result  =   0 ;
 96       for (i = 1 ; i < STR_LEN; i ++ ) {
 97          cnt  =   0 ;
 98           for (j = 0 ; j < i; j ++ )
 99               if (str[j]  >  str[i])
100                   ++ cnt;
101          result  +=  (cnt * facs[i - 1 ]);
102      }
103       return  result;
104  }
105 
106  int
107  dist( int  i,  int  j)
108  {
109       int  px, py;
110      px  =  points[i][ 0 -  points[j][ 0 ];
111      py  =  points[i][ 1 -  points[j][ 1 ];
112      px  =  px >= 0   ?  px :  - px;
113      py  =  py >= 0   ?  py :  - py;
114       return  px + py;
115  }
116 
117  /*  estimate function: manhattan distance  */
118  int
119  estimate( char   * str)
120  {
121       int  i, rt  =   0 ;
122       for (i = 0 ; i < STR_LEN; i ++ )
123           if (str[i]  !=   ' 0 ' )
124              rt  +=  distance[i][str[i] - ' 0 ' - 1 ];
125       return  rt;
126  }
127 
128  void
129  output( int  hash_value)
130  {
131       if (pre[hash_value]  ==   - 1 )
132           return ;
133      output(pre[hash_value]);
134      printf( " %c " , letters[dir[hash_value]]);
135  }
136 
137  void
138  Astar( char   * start_str,  int  start_pos)
139  {
140       int  i, th, hvalue, curp, nxtp;
141       char  nxt[STR_LEN + 1 ];
142       struct  EACH cur, tmp;
143      strcpy(queue[ 0 ].str, start_str);
144      queue[ 0 ].pos  =  start_pos;
145      queue[ 0 ].value  =  hash_func(start_str);
146      count  =   1 ;
147      mark[queue[ 0 ].value]  =   1 /*  open list  */
148      g[queue[ 0 ].value]  =   0 ;
149      h[queue[ 0 ].value]  =  estimate(start_str);
150      pre[queue[ 0 ].value]  =   - 1 ;
151      dir[queue[ 0 ].value]  =   - 1 ;
152      idx[queue[ 0 ].value]  =   0 ;
153       while (count  !=   0 ) {
154          cur  =  pop();
155           if (cur.value  ==  target) {
156              output(target);
157              printf( " \n " );
158               return ;
159          }
160          mark[cur.value]  =   2 ;
161          curp  =  cur.pos;
162           for (i = 0 ; i < 4 ; i ++ ) {
163               if (movable[curp][i]) {
164                  nxtp  =  curp  +  pos[i];
165                  strcpy(nxt, cur.str);
166                  nxt[curp]  =  nxt[nxtp];
167                  nxt[nxtp]  =   ' 0 ' ;
168                  hvalue  =  hash_func(nxt);
169                   if (mark[hvalue] == 1   &&  g[hvalue] > (g[cur.value] + 1 )) {
170                      g[hvalue]  =  g[cur.value] + 1 ;
171                      pre[hvalue]  =  cur.value;
172                      dir[hvalue]  =  i;
173                      up_heapify(idx[hvalue]);
174                  }  else   if (mark[hvalue] == 0 ) {
175                      strcpy(tmp.str, nxt);
176                      tmp.pos  =  nxtp;
177                      tmp.value  =  hvalue;
178                      mark[hvalue]  =   1 ;
179                      g[hvalue]  =  g[cur.value] + 1 ;
180                      h[hvalue]  =  estimate(nxt);
181                      pre[hvalue]  =  cur.value;
182                      dir[hvalue]  =  i;
183                      idx[hvalue]  =  count;
184                      push(tmp);
185                  }
186              }
187          }
188      }
189      printf( " unsolvable\n " );
190  }
191 
192  int
193  main( int  argc,  char   ** argv)
194  {
195       int  i, j, len, sp, cnt = 0 ;
196       char  input[STR_LEN * 5 ], num[STR_LEN + 1 ];
197      fgets(input, STR_LEN * 5 - 1 , stdin);
198      len  =  strlen(input);
199       for (i = 0 ; i < len; i ++ ) {
200           if (input[i] >= ' 0 '   &&  input[i] <= ' 8 ' )
201              num[cnt ++ =  input[i];
202           else   if (input[i] == ' x ' ) {
203              num[cnt ++ =   ' 0 ' ;
204              sp  =  cnt - 1 ;
205          }
206      }
207      num[STR_LEN]  =   ' \0 ' ;
208       for (i = 0 ; i < STR_LEN; i ++ )
209           for (j = 0 ; j < STR_LEN; j ++ )
210              distance[i][j]  =  dist(i, j);
211      memset(pre,  - 1 sizeof (pre));
212      memset(dir,  - 1 sizeof (dir));
213      memset(idx,  - 1 sizeof (idx));
214      memset(mark,  0 sizeof (mark));
215      memset(g,  0 sizeof (g));
216      memset(h,  0 sizeof (h));
217      target  =  hash_func( " 123456780 " );
218      Astar(num, sp);
219       return   0 ;
220  }

你可能感兴趣的:(PKU 1077 Eight (续))