main.cc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4. #include <queue>
  5. using std::priority_queue;
  6. #define ABS(x) ((x) < 0 ? -(x) : (x))
  7. const int dst = 123456780;
  8. const int S = 362880;
  9. const int frac[9] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
  10. int perm2no(int p) {
  11. if (p < 0) return -1;
  12. char perm[10];
  13. sprintf(perm, "%09d", p);
  14. bool used[9] = {};
  15. int n = 0;
  16. for (int i = 0; i < 9; i++) {
  17. for (int j = perm[i] - '1'; 0 <= j; j--) {
  18. if (used[j]) continue;
  19. n += frac[8 - i];
  20. }
  21. used[perm[i] - '0'] = true;
  22. }
  23. return n;
  24. }
  25. int no2perm(int n) {
  26. char perm[10];
  27. bool used[9] = {};
  28. for (int i = 0; i < 9; i++) {
  29. int j = n / frac[8 - i];
  30. n %= frac[8 - i];
  31. for (int k = 0; k < 9; k++) {
  32. if (used[k]) continue;
  33. if (j-- == 0) {
  34. used[k] = true;
  35. perm[i] = k + '0';
  36. break;
  37. }
  38. }
  39. }
  40. return atoi(perm);
  41. }
  42. int next_state(int p, char m) {
  43. char perm[10];
  44. sprintf(perm, "%09d", p);
  45. int i = 0;
  46. while (perm[i] != '0') i++;
  47. switch (m) {
  48. case 'u':
  49. if (i < 3) return -1;
  50. perm[i] = perm[i - 3];
  51. perm[i - 3] = '0';
  52. return atoi(perm);
  53. case 'd':
  54. if (8 < i + 3) return -1;
  55. perm[i] = perm[i + 3];
  56. perm[i + 3] = '0';
  57. return atoi(perm);
  58. case 'l':
  59. if (i % 3 == 0) return -1;
  60. perm[i] = perm[i - 1];
  61. perm[i - 1] = '0';
  62. return atoi(perm);
  63. case 'r':
  64. if (i % 3 == 2) return -1;
  65. perm[i] = perm[i + 1];
  66. perm[i + 1] = '0';
  67. return atoi(perm);
  68. }
  69. return -1;
  70. }
  71. bool even_perm(int s) {
  72. char perm[10];
  73. sprintf(perm, "%09d", s);
  74. int cnt = 0; // 0 is not included
  75. for (int i = 1; i < 9; i++) {
  76. if (perm[i] == '0') continue;
  77. for (int j = 0; j < i; j++)
  78. if (perm[i] < perm[j]) cnt++;
  79. }
  80. return cnt % 2 == 0;
  81. }
  82. struct Node {
  83. int s;
  84. int p;
  85. int f;
  86. int g;
  87. char m;
  88. Node(int s = 0, int p = 0, int f = 0, int g = 0, char m = 0)
  89. : s(s), p(p), f(f), g(g), m(m) {}
  90. bool operator<(const Node &that) const { return that.f < this->f; }
  91. } close[S];
  92. char moves[] = "udlr";
  93. char res[S + 1];
  94. int eval_h(int s) {
  95. int res = 0;
  96. for (int i = 8; 0 <= i; i--) {
  97. int c = s % 10;
  98. if (c != 0) {
  99. int x = (c - 1) / 3;
  100. int y = (c - 1) % 3;
  101. int cx = i / 3;
  102. int cy = i % 3;
  103. res += ABS(cx - x) + ABS(cy - y);
  104. }
  105. s /= 10;
  106. }
  107. return res;
  108. }
  109. bool a_star(int s) {
  110. if (!even_perm(s)) return false;
  111. int no = perm2no(s);
  112. close[no] = Node(s, -1);
  113. priority_queue<Node> pq;
  114. pq.push(close[no]);
  115. while (!pq.empty()) {
  116. Node cur = pq.top();
  117. pq.pop();
  118. if (cur.s == dst) return true;
  119. for (int i = 0; i < 4; i++) {
  120. char m = moves[i];
  121. int nxt = next_state(cur.s, m);
  122. no = perm2no(nxt);
  123. if (no == -1 || close[no].s != 0) continue;
  124. int h = eval_h(nxt);
  125. close[no] = Node(nxt, cur.s, cur.g + 1 + h, cur.g + 1, m);
  126. pq.push(close[no]);
  127. }
  128. }
  129. return false;
  130. }
  131. int main() {
  132. char perm[10];
  133. while (scanf("%s", &perm[0]) != EOF) {
  134. if (perm[0] == 'x') perm[0] = '0';
  135. for (int i = 1; i < 9; i++) {
  136. scanf("%s", &perm[i]);
  137. if (perm[i] == 'x') perm[i] = '0';
  138. }
  139. memset(close, 0, sizeof(close));
  140. int src = atoi(perm);
  141. if (a_star(src)) {
  142. int pos = perm2no(dst), i = 0;
  143. do {
  144. res[i++] = close[pos].m;
  145. pos = perm2no(close[pos].p);
  146. } while (pos != -1); // The (i-1)th char is 0! So i - 2
  147. for (int j = i - 2; 0 <= j; j--) printf("%c", res[j]);
  148. printf("\n");
  149. } else {
  150. printf("unsolvable\n");
  151. }
  152. }
  153. return 0;
  154. }