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

#define _USE_MATH_DEFINES
#include <algorithm>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <vector>
using namespace std;
#define rep(i, n) for (auto i = 0; i < n; i++)
#define range(i, v) for (auto &i : v)

struct init {
  init() {
    cin.tie(0);
    ios::sync_with_stdio(false);
  }
} ________init;

const int D = 7;
const int dr[] = {0, 1, 1, 0, -1, -1, 0};
const int dc[] = {-1, -1, 0, 1, 1, 0, 0};
inline bool near(int pr, int pc, int qr, int qc) {
  rep(i, D - 1) {
    if (pr + dr[i] == qr && pc + dc[i] == qc)
      return true;
  }
  return false;
}
inline bool eq_near(int pr, int pc, int qr, int qc) {
  rep(i, D) {
    if (pr + dr[i] == qr && pc + dc[i] == qc)
      return true;
  }
  return false;
}

typedef vector<int> V;
typedef vector<V> VV;
inline bool check(VV &snake, set<V> &stone) {
  int n = snake.size();
  range(it, snake) if (stone.count(it)) return false;
  rep(i, n) {
    if (i + 1 < n) {
      int j = i + 1;
      if (!near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))
        return false;
    }
    rep(j, n) if (i + 2 <= j) {
      if (eq_near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))
        return false;
    }
  }
  return true;
}

inline bool check2(int n, VV &snake, set<V> &stone) {
  if (stone.count(snake[n - 1]))
    return false;
  {
    rep(k, 2) {
      int i = n - k - 1;
      if (i >= 0 && i + 1 < (int)snake.size()) {
        int j = i + 1;
        if (!near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))
          return false;
      }
    }
    int i = n - 1;
    rep(j, n - 2) {
      if (eq_near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))
        return false;
    }
  }
  return true;
}
map<VV, int> cost;
int main() {
#ifdef INPUT_FROM_FILE
  ifstream cin("sample.in");
  ofstream cout("sample.out");
#endif
  int n, k;
  while (cin >> n, n) {

    set<V> stone;
    VV snake(n, V(2));

    range(jt, snake) range(it, jt) cin >> it;

    cin >> k;
    cost.clear();
    cost[snake] = 0;
    rep(i, k) {
      V s(2);
      range(it, s) cin >> it;
      stone.insert(s);
    }
    V goal(2);
    range(it, goal) cin >> it;
    queue<VV> que;
    que.push(snake);
    while (!que.empty()) {
      auto v = que.front();
      que.pop();
      // printf("%d\\n", cost[v]);
      if (v[0] == goal) {
        cout << cost[v] << endl;
        break;
      }
      auto u = v;
      std::function<void(int, bool)> dfs = [&](int k, bool prev_move) {
        if (k == n) {
          if (cost.count(u) == 0)
            if (20 >= cost[v] + 1 +
                          max(abs(u[0][0] - goal[0]), abs(u[0][1] - goal[1]))) {
              cost[u] = cost[v] + 1;
              que.push(u);
            }
        } else if (prev_move) {
          dfs(k + 1, false);
        } else
          rep(i, D) {
            u[k][0] += dr[i];
            u[k][1] += dc[i];
            if (check2(k + 1, u, stone))
              dfs(k + 1, i != D - 1);
            u[k][0] -= dr[i];
            u[k][1] -= dc[i];
          }
      };
      dfs(0, false);
    };
  }

  return 0;
}

Error: MLE

Fixed submission:

#define _USE_MATH_DEFINES
#include <algorithm>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <vector>
using namespace std;
#define rep(i, n) for (auto i = 0; i < n; i++)
#define range(i, v) for (auto &i : v)

struct init {
  init() {
    cin.tie(0);
    ios::sync_with_stdio(false);
  }
} ________init;

const int D = 7;
const int dr[] = {0, 1, 1, 0, -1, -1, 0};
const int dc[] = {-1, -1, 0, 1, 1, 0, 0};
bool near(int pr, int pc, int qr, int qc) {
  rep(i, D - 1) {
    if (pr + dr[i] == qr && pc + dc[i] == qc)
      return true;
  }
  return false;
}
bool eq_near(int pr, int pc, int qr, int qc) {
  rep(i, D) {
    if (pr + dr[i] == qr && pc + dc[i] == qc)
      return true;
  }
  return false;
}

typedef vector<int> V;
typedef vector<V> VV;
bool check(VV &snake, set<V> &stone) {
  int n = snake.size();
  range(it, snake) if (stone.count(it)) return false;
  rep(i, n) {
    if (i + 1 < n) {
      int j = i + 1;
      if (!near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))
        return false;
    }
    rep(j, n) if (i + 2 <= j) {
      if (eq_near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))
        return false;
    }
  }
  return true;
}

bool check2(int n, VV &snake, set<V> &stone) {
  if (stone.count(snake[n - 1]))
    return false;
  {
    rep(k, 2) {
      int i = n - k - 1;
      if (i >= 0 && i + 1 < (int)snake.size()) {
        int j = i + 1;
        if (!near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))
          return false;
      }
    }
    int i = n - 1;
    rep(j, n - 2) {
      if (eq_near(snake[i][0], snake[i][1], snake[j][0], snake[j][1]))
        return false;
    }
  }
  return true;
}
map<VV, int> cost;
int main() {
#ifdef INPUT_FROM_FILE
  ifstream cin("sample.in");
  ofstream cout("sample.out");
#endif
  int n, k;
  while (cin >> n, n) {

    set<V> stone;
    VV snake(n, V(2));

    range(jt, snake) range(it, jt) cin >> it;

    cin >> k;
    cost.clear();
    cost[snake] = 0;
    rep(i, k) {
      V s(2);
      range(it, s) cin >> it;
      stone.insert(s);
    }
    V goal(2);
    range(it, goal) cin >> it;
    queue<VV> que;
    que.push(snake);
    while (!que.empty()) {
      auto v = que.front();
      que.pop();
      // printf("%d\\n", cost[v]);
      if (v[0] == goal) {
        cout << cost[v] << endl;
        break;
      }
      auto u = v;
      std::function<void(int, bool)> dfs = [&](int k, bool prev_move) {
        if (k == n) {
          if (cost.count(u) == 0) {
            cost[u] = cost[v] + 1;
            que.push(u);
          }
        } else if (prev_move) {
          dfs(k + 1, false);
        } else
          rep(i, D) {
            u[k][0] += dr[i];
            u[k][1] += dc[i];
            if (check2(k + 1, u, stone))
              dfs(k + 1, i != D - 1);
            u[k][0] -= dr[i];
            u[k][1] -= dc[i];
          }
      };
      dfs(0, false);
    };
  }

  return 0;
}