Problem p00190 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <iostream>
#include <map>
#include <queue>
#include <sstream>
#include <string>
using namespace std;

#define REP(i, n, m) for (int i = n; i < m; i++)
#define rep(i, n) REP(i, 0, n)

class State {
public:
  string s;
  int cost;
  int idx[2];

  State(string ts, int tcost, int tidx[]) {
    s = ts;
    cost = tcost;
    idx[0] = tidx[0];
    idx[1] = tidx[1];
  }
};

int di[13][4] = {
    {-1, -1, 2, -1},  {-1, 2, 5, -1},  {0, 3, 6, 1},   {-1, -1, 7, 2},
    {-1, 5, -1, -1},  {1, 6, 9, 4},    {2, 7, 10, 5},  {3, 8, 11, 6},
    {-1, -1, -1, 7},  {5, 10, -1, -1}, {6, 11, 12, 9}, {7, -1, -1, 10},
    {10, -1, -1, -1},
};

void printPuzzle(string s) {
  cout << "  " << s.substr(0, 1) << endl;
  cout << " " << s.substr(1, 3) << endl;
  cout << s.substr(4, 5) << endl;
  cout << " " << s.substr(9, 3) << endl;
  cout << "  " << s.substr(12, 1) << endl;
  cout << "----------------------------\\n";
}

queue<State> open;
map<string, int> closed, closed2;

int main(void) {
  string alpha = "abcdefghijkl";
  int idx[] = {0, 12};

  open.push(State("abcdefghijkla", 0, idx));
  closed.insert(pair<string, int>("abcdefghijkla", 0));

  while (!open.empty()) {
    State st = open.front();
    open.pop();
    if (st.cost >= 14)
      continue;

    rep(i, 2) {
      rep(j, 4) {
        int to = di[st.idx[i]][j];
        if (to == -1)
          continue;

        string res = st.s;
        int tmp = res[st.idx[i]];
        res[st.idx[i]] = res[to];
        res[to] = tmp;

        if (closed.find(res) == closed.end()) {
          idx[0] = i == 0 ? to : st.idx[0];
          idx[1] = i == 1 ? to : st.idx[1];
          open.push(State(res, st.cost + 1, idx));
          closed.insert(pair<string, int>(res, st.cost + 1));
        }
      }
    }
  }

  while (1) {
    int x;
    cin >> x;
    if (x == -1)
      break;

    stringstream ss;
    ss << alpha[x];
    rep(i, 12) {
      cin >> x;
      ss << alpha[x];
    }

    string start = ss.str();

    while (!open.empty())
      open.pop();
    closed2.clear();

    for (idx[0] = 0; start[idx[0]] != 'a'; idx[0]++)
      ;
    for (idx[1] = start.length() - 1; start[idx[1]] != 'a'; idx[1]--)
      ;
    open.push(State(start, 0, idx));
    closed2.insert(pair<string, int>(start, 0));

    int ans = -1;

    while (!open.empty()) {
      State st = open.front();
      open.pop();
      if (closed.find(st.s) != closed.end() && st.cost + closed[st.s] <= 20) {
        ans = st.cost + closed[st.s];
        break;
      }
      if (st.cost >= 7)
        continue;

      rep(i, 2) {
        rep(j, 4) {
          int to = di[st.idx[i]][j];
          if (to == -1)
            continue;

          string res = st.s;
          int tmp = res[st.idx[i]];
          res[st.idx[i]] = res[to];
          res[to] = tmp;

          if (closed2.find(res) == closed2.end()) {
            idx[0] = i == 0 ? to : st.idx[0];
            idx[1] = i == 1 ? to : st.idx[1];
            open.push(State(res, st.cost + 1, idx));
            closed2.insert(pair<string, int>(res, st.cost + 1));
          }
        }
      }
    }

    if (ans == -1)
      cout << "NA\\n";
    else
      cout << ans << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <iostream>
#include <map>
#include <queue>
#include <sstream>
#include <string>
using namespace std;

#define REP(i, n, m) for (int i = n; i < m; i++)
#define rep(i, n) REP(i, 0, n)

class State {
public:
  string s;
  int cost;
  int idx[2];

  State(string ts, int tcost, int tidx[]) {
    s = ts;
    cost = tcost;
    idx[0] = tidx[0];
    idx[1] = tidx[1];
  }
};

int di[13][4] = {
    {-1, -1, 2, -1},  {-1, 2, 5, -1},  {0, 3, 6, 1},   {-1, -1, 7, 2},
    {-1, 5, -1, -1},  {1, 6, 9, 4},    {2, 7, 10, 5},  {3, 8, 11, 6},
    {-1, -1, -1, 7},  {5, 10, -1, -1}, {6, 11, 12, 9}, {7, -1, -1, 10},
    {10, -1, -1, -1},
};

void printPuzzle(string s) {
  cout << "  " << s.substr(0, 1) << endl;
  cout << " " << s.substr(1, 3) << endl;
  cout << s.substr(4, 5) << endl;
  cout << " " << s.substr(9, 3) << endl;
  cout << "  " << s.substr(12, 1) << endl;
  cout << "----------------------------\\n";
}

queue<State> open;
map<string, int> closed;

int main(void) {
  string alpha = "abcdefghijkl";
  int idx[] = {0, 12};

  open.push(State("abcdefghijkla", 0, idx));
  closed.insert(pair<string, int>("abcdefghijkla", 0));

  while (!open.empty()) {
    State st = open.front();
    open.pop();
    if (st.cost >= 20)
      continue;

    rep(i, 2) {
      rep(j, 4) {
        int to = di[st.idx[i]][j];
        if (to == -1)
          continue;

        string res = st.s;
        int tmp = res[st.idx[i]];
        res[st.idx[i]] = res[to];
        res[to] = tmp;

        if (closed.find(res) == closed.end()) {
          idx[0] = i == 0 ? to : st.idx[0];
          idx[1] = i == 1 ? to : st.idx[1];
          open.push(State(res, st.cost + 1, idx));
          closed.insert(pair<string, int>(res, st.cost + 1));
        }
      }
    }
  }

  while (1) {
    int x;
    cin >> x;
    if (x == -1)
      break;

    stringstream ss;
    ss << alpha[x];
    rep(i, 12) {
      cin >> x;
      ss << alpha[x];
    }

    string start = ss.str();
    map<string, int>::iterator iter = closed.find(start);
    if (iter == closed.end())
      cout << "NA\\n";
    else
      cout << iter->second << endl;
  }

  return 0;
}