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


#include <algorithm>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <queue>
#include <set>

using namespace std;

enum triangle { DOWN = 0, UP = 1 };
enum directions { RIGHT = 0, VERT = 1, LEFT = 2 };

const int dx = 101;
const int dy = 101;
const int MAX_X = 2 * dx;
const int MAX_Y = 2 * dy;

const int roll[20][3] = {
    {1, 4, 5},    {2, 0, 6},    {3, 1, 7},    {4, 2, 8},    {0, 3, 9},

    {11, 0, 10},  {12, 1, 11},  {13, 2, 12},  {14, 3, 13},  {10, 4, 14},

    {5, 9, 15},   {6, 5, 16},   {7, 6, 17},   {8, 7, 18},   {9, 8, 19},

    {16, 10, 19}, {17, 11, 15}, {18, 12, 16}, {19, 13, 17}, {15, 14, 18},
};

struct State {
  short x, y;
  char face, preface, from;
  char link[3];
  char cost;
};

State nextState(const State &st, int moveType) {
  int x = st.x;
  int y = st.y;
  int which = (abs(x) + abs(y)) % 2;
  State next;

  if (which == DOWN) {
    if (moveType == 0) { // right
      x += 1;
    } else if (moveType == 1) { // left
      x -= 1;
    } else { // up
      y += 1;
    }
  } else {
    if (moveType == 0) { // right
      x += 1;
    } else if (moveType == 1) { // down
      y -= 1;
    } else { // left
      x -= 1;
    }
  }

  next.x = x;
  next.y = y;
  next.preface = st.face;
  next.face = st.link[moveType];
  next.from = moveType;
  next.cost = st.cost + 1;

  int diff;
  for (int i = 0; i < 3; ++i) {
    if (roll[next.face][i] == st.face)
      diff = i;
  }
  for (int i = 0; i < 3; ++i) {
    if (which == DOWN) {
      if (moveType == 0) {
        next.link[(i + 2) % 3] = roll[next.face][(diff + i) % 3];
      } else if (moveType == 1) {
        next.link[(i) % 3] = roll[next.face][(diff + i) % 3];
      } else {
        next.link[(i + 1) % 3] = roll[next.face][(diff + i) % 3];
      }
    } else {
      if (moveType == 0) {
        next.link[(i + 1) % 3] = roll[next.face][(diff + i) % 3];
      } else if (moveType == 1) {
        next.link[(i + 2) % 3] = roll[next.face][(diff + i) % 3];
      } else {
        next.link[(i) % 3] = roll[next.face][(diff + i) % 3];
      }
    }
  }

  return next;
};

const int infty = 200;
bool vis[MAX_X][MAX_Y][20][20][3];

int solve(int gx, int gy, int gface) {
  queue<State> Q;
  // set<State> S;
  State init;

  // int mincost = abs(gx-dx)+abs(gy-dy);
  for (int i = 0; i < MAX_X; ++i) {     // x
    for (int j = 0; j < MAX_Y; ++j) {   // y
      for (int k = 0; k < 20; ++k) {    // face
        for (int l = 0; l < 20; ++l) {  // preface
          for (int m = 0; m < 3; ++m) { // from
            vis[i][j][k][l][m] = false;
          }
        }
      }
    }
  }

  init.x = dx;
  init.y = dy;
  init.face = 0;
  init.preface = 0;
  init.link[0] = 1;
  init.link[1] = 4;
  init.link[2] = 5;
  init.cost = 0;
  init.from = 0;
  Q.push(init);

  while (!Q.empty()) {
    State cur = Q.front();
    Q.pop();

    // maxx = max( maxx, cur.x );
    // maxy = max( maxy, cur.y );

    // cout << cur.x << ' ' << cur.y << ' ' << cur.face << ' ' << cur.preface <<
    // ' ' << cur.from << endl;
    /*
    if( vis[cur.x][cur.y][cur.face][cur.preface][cur.from] )
      continue;
    else
      vis[cur.x][cur.y][cur.face][cur.preface][cur.from] = true;
    */
    if (cur.cost > 100)
      continue;
    if (cur.cost + abs(cur.x - gx) + abs(cur.y - gy) > 100)
      continue;
    // cout << cur.x-dx << ' ' << cur.y-dy << ' ' << cur.face << endl;
    if (cur.x == gx && cur.y == gy && cur.face == gface) {
      // cout << maxx << ' ' << maxy << endl;
      return cur.cost;
    }
    for (int i = 0; i < 3; ++i) {
      State next = nextState(cur, i);
      // cout << next.x << ' ' << next.y << ' ' << next.face << ' '<<
      // next.preface << ' ' << next.from << endl;

      if (vis[next.x][next.y][next.face][next.preface][next.from])
        continue;
      else
        vis[next.x][next.y][next.face][next.preface][next.from] = true;

      Q.push(next);
    }
  }

  return -1;
}

int main() {
  int x, y, face;
  while (cin >> x >> y >> face) {
    if (x == 0 && y == 0 && face == 0)
      break;
    x += dx;
    y += dy;
    cout << solve(x, y, face) << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:


#include <algorithm>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <queue>
#include <set>

using namespace std;

enum triangle { DOWN = 0, UP = 1 };
enum directions { RIGHT = 0, VERT = 1, LEFT = 2 };

const int dx = 105;
const int dy = 105;
const int MAX_X = 2 * dx;
const int MAX_Y = 2 * dy;

const int roll[20][3] = {
    {1, 4, 5},    {2, 0, 6},    {3, 1, 7},    {4, 2, 8},    {0, 3, 9},

    {11, 0, 10},  {12, 1, 11},  {13, 2, 12},  {14, 3, 13},  {10, 4, 14},

    {5, 9, 15},   {6, 5, 16},   {7, 6, 17},   {8, 7, 18},   {9, 8, 19},

    {16, 10, 19}, {17, 11, 15}, {18, 12, 16}, {19, 13, 17}, {15, 14, 18},
};

struct State {
  int x, y, face, preface, from;
  int link[3];
  int cost;
  bool operator<(const State &t) const {
    if (x != t.x)
      return x < t.x;
    if (y != t.y)
      return y < t.y;
    if (face != t.face)
      return face < t.face;
    if (preface != t.preface)
      return preface < t.preface;
    if (from != t.from)
      return from < t.from;
    return false;
  }
};

State nextState(const State &st, int moveType) {
  int x = st.x;
  int y = st.y;
  int which = (abs(x) + abs(y)) % 2;
  State next;

  if (which == DOWN) {
    if (moveType == 0) { // right
      x += 1;
    } else if (moveType == 1) { // left
      x -= 1;
    } else { // up
      y += 1;
    }
  } else {
    if (moveType == 0) { // right
      x += 1;
    } else if (moveType == 1) { // down
      y -= 1;
    } else { // left
      x -= 1;
    }
  }

  next.x = x;
  next.y = y;
  next.preface = st.face;
  next.face = st.link[moveType];
  next.from = moveType;
  next.cost = st.cost + 1;

  int diff;
  for (int i = 0; i < 3; ++i) {
    if (roll[next.face][i] == st.face)
      diff = i;
  }
  for (int i = 0; i < 3; ++i) {
    if (which == DOWN) {
      if (moveType == 0) {
        next.link[(i + 2) % 3] = roll[next.face][(diff + i) % 3];
      } else if (moveType == 1) {
        next.link[(i) % 3] = roll[next.face][(diff + i) % 3];
      } else {
        next.link[(i + 1) % 3] = roll[next.face][(diff + i) % 3];
      }
    } else {
      if (moveType == 0) {
        next.link[(i + 1) % 3] = roll[next.face][(diff + i) % 3];
      } else if (moveType == 1) {
        next.link[(i + 2) % 3] = roll[next.face][(diff + i) % 3];
      } else {
        next.link[(i) % 3] = roll[next.face][(diff + i) % 3];
      }
    }
  }

  return next;
};

const int infty = 200;
int solve(int gx, int gy, int gface) {
  queue<State> Q;
  // set<State> S;
  State init;

  static bool vis[MAX_X][MAX_Y][20][20][3];

  // int mincost = abs(gx-dx)+abs(gy-dy);
  for (int i = 0; i < min(gx + 100, MAX_X); ++i) {   // x
    for (int j = 0; j < min(gy + 100, MAX_Y); ++j) { // y
      for (int k = 0; k < 20; ++k) {                 // face
        for (int l = 0; l < 20; ++l) {               // preface
          for (int m = 0; m < 3; ++m) {              // from
            vis[i][j][k][l][m] = false;
          }
        }
      }
    }
  }

  init.x = dx;
  init.y = dy;
  init.face = 0;
  init.preface = 0;
  init.link[0] = 1;
  init.link[1] = 4;
  init.link[2] = 5;
  init.cost = 0;
  init.from = 0;
  Q.push(init);

  while (!Q.empty()) {
    State cur = Q.front();
    Q.pop();

    // maxx = max( maxx, cur.x );
    // maxy = max( maxy, cur.y );

    // cout << cur.x << ' ' << cur.y << ' ' << cur.face << ' ' << cur.preface <<
    // ' ' << cur.from << endl;
    /*
    if( vis[cur.x][cur.y][cur.face][cur.preface][cur.from] )
      continue;
    else
      vis[cur.x][cur.y][cur.face][cur.preface][cur.from] = true;
    */
    if (cur.cost > 100)
      continue;
    // cout << cur.x-dx << ' ' << cur.y-dy << ' ' << cur.face << endl;
    if (cur.x == gx && cur.y == gy && cur.face == gface) {
      // cout << maxx << ' ' << maxy << endl;
      return cur.cost;
    }
    for (int i = 0; i < 3; ++i) {
      State next = nextState(cur, i);
      // cout << next.x << ' ' << next.y << ' ' << next.face << ' '<<
      // next.preface << ' ' << next.from << endl;

      if (vis[next.x][next.y][next.face][next.preface][next.from])
        continue;
      else
        vis[next.x][next.y][next.face][next.preface][next.from] = true;

      Q.push(next);
    }
  }

  return -1;
}

int main() {
  int x, y, face;
  while (cin >> x >> y >> face) {
    if (x == 0 && y == 0 && face == 0)
      break;
    x += dx;
    y += dy;
    cout << solve(x, y, face) << endl;
  }
  return 0;
}