dengxinyi 6 vuotta sitten
vanhempi
commit
41f358b513
1 muutettua tiedostoa jossa 43 lisäystä ja 26 poistoa
  1. 43 26
      poj/1077.eight/main.cc

+ 43 - 26
poj/1077.eight/main.cc

@@ -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");