|
@@ -1,11 +1,8 @@
|
|
|
#include <cstdio>
|
|
|
#include <cstdlib>
|
|
|
-#include <cstring>
|
|
|
#include <queue>
|
|
|
-#include <set>
|
|
|
|
|
|
using std::priority_queue;
|
|
|
-using std::set;
|
|
|
|
|
|
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
|
|
|
|
@@ -14,6 +11,7 @@ const int S = 362880;
|
|
|
const int frac[9] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
|
|
|
|
|
|
int perm2no(int p) {
|
|
|
+ if (p < 0) return -1;
|
|
|
char perm[10];
|
|
|
sprintf(perm, "%09d", p);
|
|
|
bool used[9] = {};
|
|
@@ -68,7 +66,7 @@ int next_state(int p, char m) {
|
|
|
perm[i - 1] = '0';
|
|
|
return atoi(perm);
|
|
|
case 'r':
|
|
|
- if ((i + 1) % 3 == 0) return -1;
|
|
|
+ if (i % 3 == 2) return -1;
|
|
|
perm[i] = perm[i + 1];
|
|
|
perm[i + 1] = '0';
|
|
|
return atoi(perm);
|
|
@@ -76,24 +74,33 @@ int next_state(int p, char m) {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+bool even_perm(int s) {
|
|
|
+ char perm[10];
|
|
|
+ sprintf(perm, "%09d", s);
|
|
|
+ int cnt = 0; // 0 is not included
|
|
|
+ for (int i = 1; i < 9; i++) {
|
|
|
+ if (perm[i] == '0') continue;
|
|
|
+ for (int j = 0; j < i; j++)
|
|
|
+ if (perm[i] < perm[j]) cnt++;
|
|
|
+ }
|
|
|
+ return cnt % 2 == 0;
|
|
|
+}
|
|
|
+
|
|
|
struct Node {
|
|
|
int s;
|
|
|
int p;
|
|
|
int f;
|
|
|
int g;
|
|
|
- int h;
|
|
|
char m;
|
|
|
- Node(int s = 0, int p = 0, int f = 0, int g = 0, int h = 0, char m = 0)
|
|
|
- : s(s), p(p), f(f), g(g), h(h), m(m) {}
|
|
|
+ Node(int s = 0, int p = 0, int f = 0, int g = 0, char m = 0)
|
|
|
+ : s(s), p(p), f(f), g(g), m(m) {}
|
|
|
bool operator<(const Node &that) const { return that.f < this->f; }
|
|
|
-} queue[S];
|
|
|
-
|
|
|
-int head;
|
|
|
+} close[S];
|
|
|
|
|
|
char moves[] = "udlr";
|
|
|
char res[S + 1];
|
|
|
|
|
|
-int eval_g(int s) {
|
|
|
+int eval_h(int s) {
|
|
|
int res = 0;
|
|
|
for (int i = 8; 0 <= i; i--) {
|
|
|
int c = s % 10;
|
|
@@ -109,17 +116,27 @@ int eval_g(int s) {
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
-bool a_star(int s, int t) {
|
|
|
- head = 0;
|
|
|
- queue[head] = Node(s, -1);
|
|
|
+bool a_star(int s) {
|
|
|
+ if (!even_perm(s)) return false;
|
|
|
+ int no = perm2no(s);
|
|
|
+ close[no] = Node(s, -1);
|
|
|
priority_queue<Node> pq;
|
|
|
- pq.push(queue[head]);
|
|
|
- set<int> used;
|
|
|
- used.insert(s);
|
|
|
- while (pq.size()) {
|
|
|
- Node &cur = queue[head];
|
|
|
- head++;
|
|
|
+ pq.push(close[no]);
|
|
|
+ while (!pq.empty()) {
|
|
|
+ Node cur = pq.top();
|
|
|
+ pq.pop();
|
|
|
+ if (cur.s == dst) return true;
|
|
|
+ for (int i = 0; i < 4; i++) {
|
|
|
+ char m = moves[i];
|
|
|
+ int nxt = next_state(cur.s, m);
|
|
|
+ no = perm2no(nxt);
|
|
|
+ if (no == -1 || close[no].s != 0) continue;
|
|
|
+ int h = eval_h(nxt);
|
|
|
+ close[no] = Node(nxt, cur.s, cur.g + 1 + h, cur.g + 1, m);
|
|
|
+ pq.push(close[no]);
|
|
|
+ }
|
|
|
}
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
int main() {
|
|
@@ -129,13 +146,13 @@ int main() {
|
|
|
if (perm[i] == 'x') perm[i] = '0';
|
|
|
}
|
|
|
int src = atoi(perm);
|
|
|
- if (a_star(src, dst)) {
|
|
|
- int pos = head, i = 0;
|
|
|
+ if (a_star(src)) {
|
|
|
+ int pos = perm2no(dst), i = 0;
|
|
|
do {
|
|
|
- res[i++] = queue[pos].m;
|
|
|
- pos = queue[pos].p;
|
|
|
- } while (pos != -1);
|
|
|
- for (int j = i - 1; 0 <= j; j--) printf("%c", res[j]);
|
|
|
+ res[i++] = close[pos].m;
|
|
|
+ pos = perm2no(close[pos].p);
|
|
|
+ } while (pos != -1); // The (i-1)th char is 0! So i - 2
|
|
|
+ for (int j = i - 2; 0 <= j; j--) printf("%c", res[j]);
|
|
|
printf("\n");
|
|
|
} else {
|
|
|
printf("unsolvable\n");
|