Problem p00918 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

typedef int Weight;

struct Edge {
  int src, dst;
  Weight weight;

  Edge(int src, int dst, Weight weight) : src(src), dst(dst), weight(weight) {}
};

bool operator<(const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
             e.src != f.src ? e.src < f.src
                            : e.dst < f.dst;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

int ch, cv;
const int INF = 1e9;
const Weight CH = -1;
const Weight CV = 1;
const int N = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1;
Graph g(N);
vector<string> node(N);

inline int FindIndex(const string s) {
  return lower_bound(node.begin(), node.end(), s) - node.begin();
}

void Init() {
  string perm = "012345678";
  int cnt = 0;

  do {
    node[cnt] = perm;
    cnt++;
  } while (next_permutation(perm.begin(), perm.end()));

  do {
    string tmp = perm;
    int src = FindIndex(perm);
    int index = perm.find("0");

    // right
    swap(tmp[index], tmp[(index + 1) % 9]);
    g[src].push_back(Edge(src, FindIndex(tmp), CH));
    swap(tmp[index], tmp[(index + 1) % 9]);

    // left
    swap(tmp[index], tmp[(index + 8) % 9]);
    g[src].push_back(Edge(src, FindIndex(tmp), CH));
    swap(tmp[index], tmp[(index + 8) % 9]);

    // down
    swap(tmp[index], tmp[(index + 3) % 9]);
    g[src].push_back(Edge(src, FindIndex(tmp), CV));
    swap(tmp[index], tmp[(index + 3) % 9]);
    // up
    swap(tmp[index], tmp[(index + 6) % 9]);
    g[src].push_back(Edge(src, FindIndex(tmp), CV));
  } while (next_permutation(perm.begin(), perm.end()));
}

// ダイクストラ法 O(|E|log|V|)
int ShortestPath(int start, int end) {
  typedef pair<int, int> P;
  priority_queue<P, vector<P>, greater<P>> que;
  vector<int> d(N);

  fill(d.begin(), d.end(), INF);
  d[start] = 0;
  que.push(P(0, start));

  while (!que.empty()) {
    P p = que.top();
    que.pop();
    int v = p.second;

    if (d[v] < p.first)
      continue;
    for (Edges::iterator e = g[v].begin(); e != g[v].end(); ++e) {
      Weight cost = (e->weight == CV) ? cv : ch;

      if (d[e->dst] > d[v] + cost) {
        d[e->dst] = d[v] + cost;
        que.push(P(d[e->dst], e->dst));
      }
    }
  }

  return d[end];
}

int main() {
  Init();

  while (cin >> ch >> cv, ch || cv) {
    string start, end;
    char c;

    for (int i = 0; i < 3; ++i)
      for (int j = 0; j < 3; ++j) {
        cin >> c;
        start.push_back(c);
      }
    for (int i = 0; i < 3; ++i)
      for (int j = 0; j < 3; ++j) {
        cin >> c;
        end.push_back(c);
      }

    int s = FindIndex(start), e = FindIndex(end);
    cout << ShortestPath(s, e) << endl;
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

typedef int Weight;

struct Edge {
  int src, dst;
  Weight weight;
  string node;

  Edge(int src, int dst, Weight weight, string node)
      : src(src), dst(dst), weight(weight), node(node) {}
  Edge(int src, int dst, Weight weight) : src(src), dst(dst), weight(weight) {}
};

bool operator<(const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
             e.src != f.src ? e.src < f.src
                            : e.dst < f.dst;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

int ch, cv;
const int INF = 1e9;
const Weight CH = -1;
const Weight CV = 1;
const int N = 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1;
Graph g(N);
vector<string> node(N);

inline int FindIndex(const string s) {
  return lower_bound(node.begin(), node.end(), s) - node.begin();
}

void Init() {
  string perm = "012345678";
  int cnt = 0;

  do {
    node[cnt] = perm;
    cnt++;
  } while (next_permutation(perm.begin(), perm.end()));

  do {
    string tmp = perm;
    int src = FindIndex(perm);
    int index = perm.find("0");

    // right
    swap(tmp[index], tmp[(index + 1) % 9]);
    g[src].push_back(Edge(src, FindIndex(tmp), CH, tmp));
    swap(tmp[index], tmp[(index + 1) % 9]);

    // left
    swap(tmp[index], tmp[(index + 8) % 9]);
    g[src].push_back(Edge(src, FindIndex(tmp), CH, tmp));
    swap(tmp[index], tmp[(index + 8) % 9]);

    // down
    swap(tmp[index], tmp[(index + 3) % 9]);
    g[src].push_back(Edge(src, FindIndex(tmp), CV, tmp));
    swap(tmp[index], tmp[(index + 3) % 9]);
    // up
    swap(tmp[index], tmp[(index + 6) % 9]);
    g[src].push_back(Edge(src, FindIndex(tmp), CV, tmp));
  } while (next_permutation(perm.begin(), perm.end()));
}

// ダイクストラ法 O(|E|log|V|)
int ShortestPath(int start, int end) {
  typedef pair<int, int> P;
  priority_queue<P, vector<P>, greater<P>> que;
  vector<int> d(N);

  fill(d.begin(), d.end(), INF);
  d[start] = 0;
  que.push(P(0, start));

  while (!que.empty()) {
    P p = que.top();
    que.pop();
    int v = p.second;

    if (d[v] < p.first)
      continue;
    for (Edges::iterator e = g[v].begin(); e != g[v].end(); ++e) {
      Weight cost = (e->weight == CV) ? cv : ch;

      if (d[e->dst] > d[v] + cost) {
        d[e->dst] = d[v] + cost;
        que.push(P(d[e->dst], e->dst));
      }
    }
  }

  return d[end];
}

int main() {
  Init();

  while (cin >> ch >> cv, ch || cv) {
    string start, end;
    char c;

    for (int i = 0; i < 3; ++i)
      for (int j = 0; j < 3; ++j) {
        cin >> c;
        start.push_back(c);
      }
    for (int i = 0; i < 3; ++i)
      for (int j = 0; j < 3; ++j) {
        cin >> c;
        end.push_back(c);
      }

    int s = FindIndex(start), e = FindIndex(end);
    cout << ShortestPath(s, e) << endl;
  }

  return 0;
}