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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <map>
#include <queue>
#include <string>
#include <vector>

using namespace std;

struct P {
  int bits;
  int time;
  int zero;
  P(int bits, int time, int zero) : bits(bits), time(time), zero(zero) {}
};

const int LEN = 8;
const int MAX_BIT = 8;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};

int get_bit(int num, int x) {
  if (x == MAX_BIT - 1) {
    int k = pow(LEN, x);
    return num / k;
  } else if (0 <= x && x < MAX_BIT - 1) {
    int k1 = pow(LEN, x + 1);
    int k2 = pow(LEN, x);
    return (num % k1) / k2;
  } else {
    assert(0);
  }
}

void swap_bits(int &num, int x, int y) {
  int bit_x = get_bit(num, x);
  int bit_y = get_bit(num, y);
  num -= bit_x * (int)pow(LEN, x);
  num -= bit_y * (int)pow(LEN, y);
  num += bit_x * (int)pow(LEN, y);
  num += bit_y * (int)pow(LEN, x);
}

string bits2str(int num) {
  string result;
  int div = pow(LEN, MAX_BIT - 1);
  while (div) {
    int quo = num / div;
    int rem = num % div;
    num = rem;
    div /= LEN;
    result.push_back(quo + '0');
  }
  return result;
}

int main() {
  int origin = 0;
  for (int i = 0; i < LEN; i++) {
    origin = LEN * origin + i;
  }

  queue<P> q;
  map<int, int> reach_time;

  q.push(P(origin, 0, 0));
  reach_time.insert(make_pair(origin, 0));
  while (!q.empty()) {
    P &p = q.front();
    int magic = p.bits;
#if DEBUG
    string s_magic = bits2str(magic);
#endif
    int time = p.time;
    int zero = p.zero;
    q.pop();
    for (int i = 0; i < 4; i++) {
      int x = zero / 4 + dx[i];
      int y = zero % 4 + dy[i];
      if (x >= 0 && x < 2 && y >= 0 && y < 4) {
        int new_magic = magic;
        swap_bits(new_magic, MAX_BIT - 1 - zero, MAX_BIT - 1 - (4 * x + y));
#if DEBUG
        string s_new_magic = bits2str(new_magic);
#endif
        if (reach_time.find(new_magic) == reach_time.end()) {
          reach_time.insert(make_pair(new_magic, time + 1));
          q.push(P(new_magic, time + 1, 4 * x + y));
        }
      }
    }
  }

  while (1) {
    int ret;
    int puzzle = 0;
    for (int i = 0; i < LEN; i++) {
      int tmp;
      ret = scanf("%d", &tmp);
      if (ret < 0)
        break;
      puzzle = LEN * puzzle + tmp;
    }
    if (ret < 0)
      break;
    printf("%d\\n", reach_time[puzzle]);
  }
  return 0;
}

Error: TLE

Fixed submission:


#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

struct P {
  int bits;
  int time;
  int zero;
  P(int bits, int time, int zero) : bits(bits), time(time), zero(zero) {}
};

const int LEN = 8;
const int MAX_BIT = 8;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};

int get_bit(int num, int x) {
  if (x == MAX_BIT - 1) {
    int k = pow(LEN, x);
    return num / k;
  } else if (0 <= x && x < MAX_BIT - 1) {
    int k1 = pow(LEN, x + 1);
    int k2 = pow(LEN, x);
    return (num % k1) / k2;
  } else {
    assert(0);
  }
}

void swap_bits(int &num, int x, int y) {
  int bit_x = get_bit(num, x);
  int bit_y = get_bit(num, y);
  num -= bit_x * (int)pow(LEN, x);
  num -= bit_y * (int)pow(LEN, y);
  num += bit_x * (int)pow(LEN, y);
  num += bit_y * (int)pow(LEN, x);
}

string bits2str(int num) {
  string result;
  int div = pow(LEN, MAX_BIT - 1);
  while (div) {
    int quo = num / div;
    int rem = num % div;
    num = rem;
    div /= LEN;
    result.push_back(quo + '0');
  }
  return result;
}

int main() {
  int origin = 0;
  for (int i = 0; i < LEN; i++) {
    origin = LEN * origin + i;
  }
  while (1) {
    int puzzle = 0;
    queue<P> q;
    set<int> reached;
    int ret;
    int zero = -1;
    for (int i = 0; i < LEN; i++) {
      int tmp;
      ret = scanf("%d", &tmp);
      if (ret < 0)
        break;
      if (tmp == 0)
        zero = i;
      puzzle = LEN * puzzle + tmp;
    }
    if (ret < 0)
      break;
    assert(zero >= 0);

    int result = -1;
    q.push(P(puzzle, 0, zero));
    reached.insert(puzzle);
    while (!q.empty()) {
      P &p = q.front();
      int magic = p.bits;
#if DEBUG
      string s_magic = bits2str(magic);
#endif
      int time = p.time;
      int zero = p.zero;
      q.pop();
      if (magic == origin) {
        result = time;
        break;
      }
      for (int i = 0; i < 4; i++) {
        int x = zero / 4 + dx[i];
        int y = zero % 4 + dy[i];
        if (x >= 0 && x < 2 && y >= 0 && y < 4) {
          int new_magic = magic;
          swap_bits(new_magic, MAX_BIT - 1 - zero, MAX_BIT - 1 - (4 * x + y));
#if DEBUG
          string s_new_magic = bits2str(new_magic);
#endif
          if (reached.find(new_magic) == reached.end()) {
            reached.insert(new_magic);
            q.push(P(new_magic, time + 1, 4 * x + y));
          }
        }
      }
    }
    printf("%d\\n", result);
  }

  return 0;
}