用 A* 解决八数码问题

Description

The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as: 
 1  2  3  4 

 5  6  7  8 

 9 10 11 12 

13 14 15  x 

where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle: 
 1  2  3  4    1  2  3  4    1  2  3  4    1  2  3  4 

 5  6  7  8    5  6  7  8    5  6  7  8    5  6  7  8 

 9  x 10 12    9 10  x 12    9 10 11 12    9 10 11 12 

13 14 11 15   13 14 11 15   13 14  x 15   13 14 15  x 

           r->           d->           r-> 

The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively. 

Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and 
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course). 

In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three 
arrangement. 

Input

You will receive a description of a configuration of the 8 puzzle. The description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle 
 1  2  3 

 x  4  6 

 7  5  8 

is described by this list: 
 1 2 3 x 4 6 7 5 8 

Output

You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line.

Sample Input

 2  3  4  1  5  x  7  6  8 

Sample Output

ullddrurdllurdruldr

 

 

 

 

  1. #include <iostream>8 s% W2 b- F3 j$ Y4 o
  2. #include <cstdio>3 _  h, ^$ P9 ?/ ?
  3. #include <cstring>

  4. using namespace std;
  5. 9 S+ n& Q  g  R4 y
  6. #define HEAP_PARENT(i)                        (i >> 1); n- q# z9 x0 {. O) L) c2 Q
  7. #define HEAP_LEFT(i)                        (i << 1)
  8. #define HEAP_RIGHT(i)                        ((i << 1) + 1)
  9. #define HEAP_KEY(i)                                (heap[i].key)3 u: O+ O/ {; {+ T

  10. const int heap_max = 400000;% U9 m4 p4 [+ F4 ^/ N+ s3 ?2 e
  11. struct heap_data {  A$ }. b  n& m& F6 t) L9 Q  b
  12.         int step; // depth
  13.         int key; // f5 o, v. P/ t, \3 _' h" B
  14.         int v; // node8 F/ m+ u1 [/ a: `
  15.         unsigned int path[4]; // path
  16. } heap[heap_max] = {0};" j: r$ A- F) R0 L. j# `# T" U+ K
  17. 9 r. o  ?# L1 S& @  D5 B0 a
  18. class class_heap {
  19. private:
  20.         int heap_size;6 ~1 u9 ~8 s, d$ @

  21.         void swap(heap_data &arg1, heap_data &arg2)
  22.         {
  23.                 heap_data temp_heap;        ' J# i5 _0 ~1 r6 f- \
  24.                 temp_heap = arg1; arg1 = arg2; arg2 = temp_heap;
  25.         }

  26.         int heap_min_up(int node)$ R) v: _, }. G! s6 \7 p/ w
  27.         {: \1 }4 o  @  |8 k2 g3 F5 ]
  28.                 int parent;
  29. - E- R* q. z; a+ q- m; |
  30.                 parent = HEAP_PARENT(node);% ?  I! b) g( P+ y6 V3 w( g
  31.                 if (node > 1 && HEAP_KEY(parent) > HEAP_KEY(node)) {% o5 a1 i/ j8 m! M& w/ h" V6 ~% b
  32.                         swap(heap[parent], heap[node]);. K, R  `8 l: g: K) {
  33.                         return heap_min_up(parent);: t2 F9 `* [2 K* Y4 ~. C- {
  34.                 } 
  35.                 return node;
  36.         }

  37.         int heap_min_down(int node)
  38.         {
  39.                 int left, right;
  40.                 int smallest = node;( l" d  t3 R) u5 x

  41.                 left = HEAP_LEFT(node);! I1 P8 ]+ r- b5 h+ e: D# f
  42.                 right = HEAP_RIGHT(node);- ~  o& P. {- h* N. m
  43.                 if (left <= heap_size && HEAP_KEY(left) < HEAP_KEY(node)) {
  44.                         smallest = left;
  45.                 }9 b3 I. \- X: R% C, i
  46.                 if (right <= heap_size && HEAP_KEY(right) < HEAP_KEY(smallest)) {" C6 o( c1 N5 N; t/ z
  47.                         smallest = right;$ ~" S# E. C! R; ]3 m
  48.                 }
  49.                 if (smallest != node) {
  50.                         smallest = 0;' M/ Y. ^" t- Q  x
  51.                         if (left <= heap_size) {7 A* k  X( e+ l
  52.                                 smallest = left;
  53.                         }  R7 W) p# a2 X
  54.                         if (right <= heap_size && HEAP_KEY(right) < HEAP_KEY(left)) {
  55.                                 smallest = right;
  56.                         }
  57.                         if (smallest) {
  58.                                 swap(heap[smallest], heap[node]);7 L4 D6 I4 E' o. E; T
  59.                                 return heap_min_down(smallest);
  60.                         }/ i" V) y8 e8 N" K; `  d5 f2 e1 k
  61.                 }
  62.                 return node;* o/ ?+ {: ]: {  ?
  63.         }
  64. 2 y. g$ I% L0 B% L( C( F4 w
  65. public:" C: u! Z9 C( v
  66.         class_heap() { heap_size = 0; }2 Y: _4 R# |: C$ n
  67. / j- }* e3 i( }
  68.         void insert(heap_data key)
  69.         {; h/ X& Q' {7 y1 O- ?& G" O
  70.                 heap[++heap_size] = key;/ K+ `2 F( @  r' V! n/ \: {
  71.                 heap_min_up(heap_size);
  72.         }

  73.         heap_data extract_min()  s0 ^: M7 L! t) a8 t
  74.         {
  75.                 heap_data result = heap[1];

  76.                 swap(heap[1], heap[heap_size--]);
  77.                 heap_min_down(1);+ t1 w0 h- ^$ N* h+ h/ k& {3 B, H
  78.                 return result;
  79.         }6 _! L1 z9 g1 I
  80. ( U7 Z+ H! N3 R) R( A8 `% k
  81.         bool empty()
  82.         {9 C$ P( T' x, [6 q: i
  83.                 return (heap_size == 0);
  84.         }1 N4 [# g' t) {: x6 O2 I
  85. };5 |5 y; U6 r: K( e2 x

  86. class_heap heap_table;
  87. bool hash[400000] = {0};- t! b% r! Z, I7 v
  88. const int dstst = 123456780;4 L3 \; X. i6 ?
  89. const int table[10] = {0, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};. ?, l- h; `. q6 N. @9 `/ s
  90. const int markl[10][5] = {  ' D! W7 i9 @0 N' v. s- Q
  91.         {0, 0, 0, 0, 0},/ b( {- e/ u% m$ `+ l2 q: W
  92.         {0, 2, 0, 0, 4},
  93.         {0, 3, 1, 0, 5},' [- `3 w/ d% q, ?8 }# ?
  94.         {0, 0, 2, 0, 6},9 {; X' `8 w( \5 E$ O. n$ j) ^
  95.         {0, 5, 0, 1, 7},
  96.         {0, 6, 4, 2, 8},
  97.         {0, 0, 5, 3, 9}," t7 B1 ~) i8 \  I- |2 Y
  98.         {0, 8, 0, 4, 0},
  99.         {0, 9, 7, 5, 0},- J! w' f5 C2 l0 g6 z  s
  100.         {0, 0, 8, 6, 0}0 C6 L; x: F, E+ t
  101. };* l9 Z: A. Y" }9 J0 k* a1 ^  a9 L
  102. const char markc[5] = {0, 'r', 'l', 'u', 'd'};
  103. const int fac[10] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
  104. 1 S. z2 g1 D8 w0 \6 @+ W
  105. int calc_hash(int key)
  106. {6 j# d4 F& }) \, D- u  |4 J
  107.         int result = 0;! U. v( ~! ^0 B' r& ^6 R+ R
  108.         int decode[10] = {0};' s1 h+ T6 [" P2 g" M2 H

  109.         for (int i = 9; i > 0; --i) {
  110.                 decode[i] = key % 10;
  111.                 key /= 10;# a/ D9 v+ ~9 X3 O
  112.         }7 H' C  h/ u  |) ^) ?
  113.         for (int i = 1; i <= 9; ++i) {+ t4 V3 p2 g, L, `7 q0 m( J
  114.                 for (int j = i + 1; j <= 9; ++j) {# u" `$ T; F% U5 G2 k( ]
  115.                         if (decode[j] < decode[i]) {8 N+ X4 l: I; `5 T3 B) |8 G
  116.                                 result += fac[9 - i];8 [0 G. M$ v8 j
  117.                         }! B( U; g( [- g
  118.                 }                . }8 C5 U3 x1 [1 p2 g4 ?
  119.         }' Q, ?8 i& @0 O% E* D5 I
  120.         return result;4 v% N' W5 z# r; i4 L
  121. }9 z! Q/ v- M8 i& q# i2 M
  122. 1 i1 o, g* g5 Q2 o, M& F, A* Z
  123. int calc_h(int key)
  124. {$ i. F* [' z3 w: K7 @: o
  125.         int key1, key2, result;. _, e# h# y! U# L6 n' t& e
  126. 8 ?. o* w- i  ]$ ]/ U
  127.         key1 = dstst; key2 = key; result = 0;
  128.         for (int i = 1; i <= 9; ++i) {; V6 `6 h; d2 m! z- O
  129.                 if ((key1 % 10 != key2 % 10) && (key2 % 10 != 0)) {% s8 ~3 S  A1 b5 }: y1 q+ l+ S# }
  130.                         ++result;
  131.                 }
  132.                 key1 /= 10;$ z* j+ T4 A0 U3 z2 E; t
  133.                 key2 /= 10;
  134.         }9 h: ]7 [/ m+ q- V
  135.         return result;1 N3 @( D) H. P: F5 l/ @
  136. }

  137. void expand_node(heap_data old_state)
  138. {
  139.         int i, n, k, t, h;+ R! I' T3 R* V! A/ D, i8 Y$ h
  140.         int decode[10] = {0};
  141.         heap_data new_state;
  142. & G, _5 B& d2 h" e2 @/ \
  143.         t = old_state.v;
  144.         for (i = 9; i > 0; --i) {- O. h/ i: [/ ?1 B0 \) V+ k' k
  145.                 decode[i] = t % 10;7 |$ x" v# @1 S5 r% n/ B
  146.                 t /= 10;
  147.                 if (decode[i] == 0) {
  148.                         k = i;& [/ D. D$ s5 h2 E
  149.                 }
  150.         }  P' j1 S* ]$ b: ~( O
  151.         for (i = 1; i <= 4; ++i) {7 b! X% b! m. O+ H1 o
  152.                 n = markl[k][i];* e. C4 N5 O4 ^! Q$ s3 M
  153.                 if (n != 0) {) p8 y1 @0 E$ `, X. z' J3 v+ p- a2 |' I
  154.                         t = old_state.v;
  155.                         t -= table[n] * decode[n];( r$ }* [0 k  [+ |( ]
  156.                         t += table[k] * decode[n];                        ) I0 |  D3 a3 @# c
  157.                         h = calc_hash(t);
  158.                         if (!hash[h]) {
  159.                                 new_state.v = t;. l! t1 f' p( U
  160.                                 new_state.key = old_state.step + calc_h(t);                                
  161.                                 new_state.step = old_state.step + 1;
  162.                                 memcpy(new_state.path, old_state.path, 16);
  163.                                 new_state.path[old_state.step / 16] |= ((i - 1) << old_state.step % 16 * 2);
  164.                                 hash[h] = true;
  165.                                 heap_table.insert(new_state);% H  l4 q0 a8 |5 }) A+ ^9 ^! x
  166.                         }# ?: _9 e& |2 Y' R( H9 k
  167.                 }
  168.         }( A+ A( m8 @. K' C, X5 D. @( m
  169. }
  170. + g, }3 M7 Y; k/ o: m% F
  171. void astar_search()7 E8 [( s4 ^* P+ m, ?1 n
  172. {
  173.         heap_data node;1 a" v6 c# |% A. ?5 ]7 K
  174.         int flag = false;

  175.         while (!heap_table.empty()) {; A7 n6 `+ r! z; p
  176.                 node = heap_table.extract_min();3 y" m- j( U, g% ~1 J5 {( W; Y, v
  177.                 if (node.v == dstst) {" W, ]2 }0 w. S8 w
  178.                         for (int i = 0; i < node.step; ++i) {
  179.                                 cout<<markc[node.path[i / 16] % 4 + 1];
  180.                                 node.path[i / 16] >>= 2;. ]  a- {3 y/ ^' f% I' C
  181.                         }$ n$ `( H6 ?# I' a  T4 K
  182.                         flag = true;
  183.                         break;
  184.                 } else {- X4 f" N" ?5 q
  185.                         expand_node(node);
  186.                 }/ x+ Y$ t) j0 c% W& [* Q6 i: N$ X
  187.         }* ?/ M6 L+ n: m& U
  188.         if (!flag) {
  189.                 cout<<"unsolvable"<<endl;# O7 y4 a1 i. I8 P0 m# C8 f* g8 i
  190.         }4 ~/ i9 \" b) L+ T2 Z# v! p( C
  191. }

  192. int main()
  193. {
  194.         int src = 0;6 r! \5 ]3 {: {
  195.         char ch;% l0 `8 c! ]. {$ O# b+ I" u* u, t; V$ m" y
  196.         heap_data srcst;

  197.         for (int i = 1; i <= 9; ++i) {
  198.                 cin>>ch;5 j3 I, e& Q4 a2 }' G5 i# s
  199.                 if (ch != 'x') {
  200.                         ch -= '0';
  201.                         src += table[i] * ch;
  202.                 }
  203.         }
  204.         hash[calc_hash(src)] = true;9 Z2 s+ N& x& e+ M- e! g
  205.         srcst.v = src; 8 w" Q- z2 g- H1 A, D2 O) d8 z( m
  206.         srcst.key = calc_h(src); ( I+ P  ]3 e7 ]/ }3 R$ x
  207.         srcst.step = 0; 
  208.         memset(srcst.path, 0, 16);
  209.         heap_table.insert(srcst);4 X6 s8 I/ I  o( b% q
  210.         astar_search();
  211.         return 0;
  212. }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(问题)