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

#include <bits/stdc++.h>
using namespace std;

int h, w;
vector<string> field;
string s;
int p, cnt;
int y, x;
int dir;
int dy[] = {-1, 0, 1, 0};
int dx[] = {0, 1, 0, -1};
int used[50][50][1001][4];

void program();
void statement();
void _if();
void _while();
void act();
bool expr();

void skip() {
  int icnt = 0;
  int wcnt = 0;
  while (icnt >= 0 && wcnt >= 0) {
    if (s[p] == '[')
      icnt++;
    if (s[p] == ']')
      icnt--;
    if (s[p] == '{')
      wcnt++;
    if (s[p] == '}')
      wcnt--;
    p++;
  }
}

void flip() { dir = (dir + 2) % 4; }
bool iswall() { return field[y + dy[dir]][x + dx[dir]] == '#'; }
bool end() { return p >= s.size() || s[p] == ']' || s[p] == '}'; }

void program() {
  while (!end()) {
    statement();
  }
  return;
}

void statement() {
  if (s[p] == '[') {
    _if();
    return;
  }
  if (s[p] == '{') {
    _while();
    return;
  }
  act();
  return;
}

void _if() {
  assert(s[p] == '[');
  p++;
  if (!expr()) {
    skip();
    return;
  }
  program();
  assert(s[p] == ']');
  p++;
  return;
}

void _while() {
  while (true) {
    if (used[y][x][p][dir]) {
      throw "nonFin";
    }
    used[y][x][p][dir] = true;

    int prep = p;
    assert(s[p] == '{');
    p++;
    if (!expr()) {
      skip();
      return;
    }
    program();
    assert(s[p] == '}');
    p = prep;
  }
}

void judge() {
  if (field[y][x] == 'g')
    throw "Fin";
}

void act() {
  cnt++;
  char op = s[p];
  p++;
  switch (op) {
  case '^':
    if (!iswall()) {
      y = y + dy[dir];
      x = x + dx[dir];
    }
    judge();
    return;
  case 'v':
    flip();
    if (!iswall()) {
      y = y + dy[dir];
      x = x + dx[dir];
    }
    flip();
    judge();
    return;
  case '<':
    dir = (dir + 3) % 4;
    return;
  case '>':
    dir = (dir + 1) % 4;
    return;
  }
  throw "Act Error";
}

bool expr() {
  bool hoge = (s[p] != '~');
  if (s[p] == '~')
    p++;
  char op = s[p];
  p++;
  switch (op) {
  case 'N':
    return !((dir == 0) ^ hoge);
  case 'E':
    return !((dir == 1) ^ hoge);
  case 'S':
    return !((dir == 2) ^ hoge);
  case 'W':
    return !((dir == 3) ^ hoge);
  case 'C':
    return !(iswall() ^ hoge);
  case 'T':
    return hoge;
  }
  throw "Error Check";
}

void run() {
  cnt = 0, p = 0, dir = 0;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (field[i][j] == 's') {
        y = i;
        x = j;
      }
    }
  }
  try {
    program();
  } catch (const char *ex) {
    if (ex == "Fin") {
      return;
    } else if (ex == "nonFin") {
      cnt = -1;
      return;
    } else {
      cout << ex << endl;
      abort();
    }
  }
  return;
}

int main() {
  cin >> h >> w;
  field.resize(h);
  for (int i = 0; i < h; i++)
    cin >> field[i];
  cin >> s;
  run();
  if (field[y][x] != 'g')
    cnt = -1;
  cout << cnt << endl;
  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

int h, w;
vector<string> field;
string s;
int p, cnt;
int y, x;
int dir;
int dy[] = {-1, 0, 1, 0};
int dx[] = {0, 1, 0, -1};
vector<vector<vector<vector<int>>>> used;

void program();
void statement();
void _if();
void _while();
void act();
bool expr();

void skip() {
  int icnt = 0;
  int wcnt = 0;
  while (icnt >= 0 && wcnt >= 0) {
    if (s[p] == '[')
      icnt++;
    if (s[p] == ']')
      icnt--;
    if (s[p] == '{')
      wcnt++;
    if (s[p] == '}')
      wcnt--;
    p++;
  }
}

void flip() { dir = (dir + 2) % 4; }
bool iswall() { return field[y + dy[dir]][x + dx[dir]] == '#'; }
bool end() { return p >= s.size() || s[p] == ']' || s[p] == '}'; }

void program() {
  while (!end()) {
    statement();
  }
  return;
}

void statement() {
  if (s[p] == '[') {
    _if();
    return;
  }
  if (s[p] == '{') {
    _while();
    return;
  }
  act();
  return;
}

void _if() {
  assert(s[p] == '[');
  p++;
  if (!expr()) {
    skip();
    return;
  }
  program();
  assert(s[p] == ']');
  p++;
  return;
}

void _while() {
  while (true) {
    if (used[y][x][p][dir]) {
      throw "nonFin";
    }
    used[y][x][p][dir] = true;

    int prep = p;
    assert(s[p] == '{');
    p++;
    if (!expr()) {
      skip();
      return;
    }
    program();
    assert(s[p] == '}');
    p = prep;
  }
}

void judge() {
  if (field[y][x] == 'g')
    throw "Fin";
}

void act() {
  cnt++;
  char op = s[p];
  p++;
  switch (op) {
  case '^':
    if (!iswall()) {
      y = y + dy[dir];
      x = x + dx[dir];
    }
    judge();
    return;
  case 'v':
    flip();
    if (!iswall()) {
      y = y + dy[dir];
      x = x + dx[dir];
    }
    flip();
    judge();
    return;
  case '<':
    dir = (dir + 3) % 4;
    return;
  case '>':
    dir = (dir + 1) % 4;
    return;
  }
  throw "Act Error";
}

bool expr() {
  bool hoge = (s[p] != '~');
  if (s[p] == '~')
    p++;
  char op = s[p];
  p++;
  switch (op) {
  case 'N':
    return !((dir == 0) ^ hoge);
  case 'E':
    return !((dir == 1) ^ hoge);
  case 'S':
    return !((dir == 2) ^ hoge);
  case 'W':
    return !((dir == 3) ^ hoge);
  case 'C':
    return !(iswall() ^ hoge);
  case 'T':
    return hoge;
  }
  throw "Error Check";
}

void run() {
  cnt = 0, p = 0, dir = 0;
  used.resize(h, vector<vector<vector<int>>>(
                     w, vector<vector<int>>(s.size() + 1, vector<int>(4, 0))));
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (field[i][j] == 's') {
        y = i;
        x = j;
      }
    }
  }
  try {
    program();
  } catch (const char *ex) {
    if (ex == "Fin") {
      return;
    } else if (ex == "nonFin") {
      cnt = -1;
      return;
    } else {
      cout << ex << endl;
      abort();
    }
  }
  return;
}

int main() {
  cin >> h >> w;
  field.resize(h);
  for (int i = 0; i < h; i++)
    cin >> field[i];
  cin >> s;
  run();
  if (field[y][x] != 'g')
    cnt = -1;
  cout << cnt << endl;
  return 0;
}