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

#include <cassert>
#include <cctype>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

#define NMAX 11
#define MAX 16

using namespace std;

typedef pair<const char *, int> parsed;
typedef pair<bool, int> bnfm;

parsed expr(const char *);
parsed term(const char *);
parsed fact(const char *);

bnfm Ex(int pos, const string &s);
bnfm N0(int pos, const string &s);

parsed expr(const char *p) {
  parsed r = term(p);
  if (r.first == NULL)
    return r; // parse error
  while (*(r.first) == '+' || *(r.first) == '-') {
    const char *op = r.first;
    parsed l = term(op + 1);
    if (l.first == NULL)
      return l;

    if (*op == '+') {
      r.first = l.first;
      r.second = r.second + l.second;
    } else {
      r.first = l.first;
      r.second = r.second - l.second;
    }
  }
  return r;
}

parsed term(const char *p) {
  parsed r = fact(p);
  if (r.first == NULL)
    return r;
  while (*(r.first) == '*' || *(r.first) == '/') {
    const char *op = r.first;
    parsed l = fact(op + 1);
    if (l.first == NULL)
      return l;

    if (*op == '*') {
      r.first = l.first;
      r.second = r.second * l.second;
    } else {
      r.first = l.first;
      if (l.second == 0 || r.second % l.second != 0)
        return parsed(NULL, -1);
      r.second = int(r.second / l.second);
    }
  }
  return r;
}

inline parsed fact(const char *p) {
  if (*p == '(') {
    // new expression
    parsed tp = expr(p + 1);
    if (tp.first == NULL)
      return tp;
    return parsed(tp.first + 1, tp.second);
  }
  if (*p == '-') {
    // negative fact
    parsed tp = fact(p + 1);
    if (tp.first == NULL)
      return tp;
    tp.second *= -1;
    return tp;
  }
  if (isdigit(*p)) {
    // number
    int num = *p - '0';
    while (isdigit(*(++p))) {
      num *= 10;
      num += *p - '0';
    }
    return parsed(p, num);
  } else
    assert(0);
  return parsed(NULL, 0);
}

inline bool Eq(const string &s) {
  int pos = 0;
  bnfm r = Ex(pos, s);
  if (!r.first)
    return false;
  pos = r.second;
  if (pos >= s.length())
    return false;
  if (s[pos] != '=')
    return false;
  ++pos;
  r = Ex(pos, s);
  if (!r.first)
    return false;
  if (r.second < s.length())
    return false;
  return true;
}

bnfm Ex(int pos, const string &s) {
  if (pos >= s.length())
    return bnfm(false, pos);
  bnfm r = N0(pos, s);
  if (!r.first)
    return bnfm(false, r.second);
  pos = r.second;
  if (pos >= s.length())
    return bnfm(true, pos);
  while (s[pos] == '+' || s[pos] == '-' || s[pos] == '*' || s[pos] == '/') {
    bnfm r = N0(pos + 1, s);
    if (!r.first)
      return bnfm(false, r.second);
    pos = r.second;
    if (pos >= s.length())
      break;
  }
  return bnfm(true, pos);
}

bnfm N0(int pos, const string &s) {
  if (pos >= s.length())
    return bnfm(false, pos);
  if (!isdigit(s[pos]))
    return bnfm(false, pos + 1);
  if (s[pos] == '0') {
    if (pos + 1 < s.length()) {
      if (isdigit(s[pos + 1]))
        return bnfm(false, pos + 2);
    }
    return bnfm(true, pos + 1);
  } else {
    while (isdigit(s[pos])) {
      ++pos;
      if (pos >= s.length())
        break;
    }
    return bnfm(true, pos);
  }
}

bool Evaluate(const string &s) {
  string s1, s2;
  int i, j;
  for (i = 0; i < s.length(); ++i) {
    if (s[i] == '=')
      break;
    else
      s1 += s[i];
  }
  for (j = i + 1; j < s.length(); ++j) {
    s2 += s[j];
  }
  parsed p1 = expr(s1.c_str());
  parsed p2 = expr(s2.c_str());
  if (p1.first == NULL || p2.first == NULL)
    return false;
  if (p1.second == p2.second)
    return true;
  else
    return false;
}

bool Judge(const vector<string> &eqs) {

  for (int i = 0; i < eqs.size(); ++i) {
    if (eqs[i].find('.') == string::npos) {
      if (!Eq(eqs[i]))
        return false;
      if (!Evaluate(eqs[i]))
        return false;
    }
  }
  return true;
  /*
  const int di [] = {-1,0,1,0};
  const int dj [] = {0,1,0,-1};

  for(int i = 0; i < H; ++i){
    for(int j = 0; j < W; ++j){
      if( pzl[i+1][j+1] != '#' ){
        for(int l = 0; l < sizeof(di)/sizeof(*di); ++l){
          if( l == 1 || l == 2 ) continue;
          int ti = i + 1 + di[l]; int tj = j + 1 + dj[l];
          if( pzl[ti][tj] == '#' ){
            int dir = (l+2)%(sizeof(di)/sizeof(*di));
            ti = i+1+di[dir]; tj = j+1+dj[dir];
            string eq;
            eq += pzl[i+1][j+1];
            while(pzl[ti][tj]!='#'){
              eq += pzl[ti][tj]; ti += di[dir]; tj += dj[dir];
            }
            if( eq.length() >= 3 && eq.find('.') == string::npos ){
              if( !Eq(eq) ) return false;
              if( !Evaluate( eq ) ) return false;
            }
            eq.clear();
          }
        }
      }
    }
  }
  return true;
  */
}

bool operator<(const pair<int, int> &a, const pair<int, int> &b) {
  return a.first == b.first ? a.second < b.second : a.first < b.first;
}

bool dfs(int n, int now, const vector<pair<int, int>> &hole_pos,
         map<pair<int, int>, vector<pair<int, int>>> &meq, vector<string> &eqs,
         bool vis[NMAX], char holes[NMAX], int H, int W, char pzl[][MAX]) {

  if (!Judge(eqs)) {
    return false;
  } else if (now == hole_pos.size()) {
    return true;
  }

  for (int i = 0; i < n; ++i) {
    if (!vis[i]) {
      const vector<pair<int, int>> &v = meq[hole_pos[now]];
      // vector<string> teqs = eqs;
      // cout << "DOT POS=" << hole_pos[now].first << ' ' <<
      // hole_pos[now].second << " : ";
      for (int j = 0; j < v.size(); ++j) {
        // cout << v[j].first << ' ' << v[j].second << ',';
        eqs[v[j].first][v[j].second] = holes[i];
      }
      /*
      cout << endl;
      for(int j = 0; j < teqs.size(); ++j){
        cout << teqs[j] << endl;
      }
      cout << endl;
      */

      vis[i] = true;
      if (dfs(n, now + 1, hole_pos, meq, eqs, vis, holes, H, W, pzl))
        return true;
      vis[i] = false;

      for (int j = 0; j < v.size(); ++j) {
        eqs[v[j].first][v[j].second] = '.';
      }
    }
  }
  return false;
}

int main(void) {
  while (true) {
    int H, W;
    char pzl[MAX][MAX];
    bool vis[NMAX] = {
        false,
    };
    vector<pair<int, int>> hole_pos;
    vector<string> eqs;
    map<pair<int, int>, vector<pair<int, int>>> meq;

    for (int i = 0; i < MAX; ++i)
      for (int j = 0; j < MAX; ++j)
        pzl[i][j] = '#';

    cin >> H >> W;
    if (H == 0 && W == 0)
      break;
    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        cin >> pzl[i + 1][j + 1];
        if (pzl[i + 1][j + 1] == '.') {
          hole_pos.push_back(make_pair(i + 1, j + 1));
        }
      }
    }

    int n, num = 0;
    cin >> n;
    int p[n];
    char holes[n];
    for (int i = 0; i < n; ++i) {
      char d;
      cin >> d;
      holes[num++] = d;
      p[i] = i;
    }

    const int di[] = {-1, 0, 1, 0};
    const int dj[] = {0, 1, 0, -1};

    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        if (pzl[i + 1][j + 1] != '#') {
          for (int l = 0; l < sizeof(di) / sizeof(*di); ++l) {
            if (l == 1 || l == 2)
              continue;
            int ti = i + 1 + di[l];
            int tj = j + 1 + dj[l];
            if (pzl[ti][tj] == '#') {
              int dir = (l + 2) % (sizeof(di) / sizeof(*di));
              ti = i + 1;
              tj = j + 1;
              string eq;
              vector<pair<int, int>> poss;
              vector<int> ats;
              while (pzl[ti][tj] != '#') {
                eq += pzl[ti][tj];
                if (pzl[ti][tj] == '.') {
                  poss.push_back(make_pair(ti, tj));
                  ats.push_back(eq.length() - 1);
                }
                ti += di[dir];
                tj += dj[dir];
              }
              if (eq.length() >= 3) {
                eqs.push_back(eq);
                // cout << "EQ : " << eq << endl;
                // cout << "DOT ATS : ";
                for (int i = 0; i < poss.size(); ++i) {
                  // cout << ats[i] << ' ';
                  meq[poss[i]].push_back(make_pair(eqs.size() - 1, ats[i]));
                }
                // cout << endl;
              }
            }
          }
        }
      }
    }

    if (dfs(n, 0, hole_pos, meq, eqs, vis, holes, H, W, pzl)) {
      cout << "Yes" << endl;
    } else {
      cout << "No" << endl;
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <cassert>
#include <cctype>
#include <cmath>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <vector>

#define NMAX 11
#define MAX 16

using namespace std;

typedef pair<const char *, int> parsed;
typedef pair<bool, int> bnfm;

parsed expr(const char *);
parsed term(const char *);
parsed fact(const char *);

bnfm Ex(int pos, const string &s);
bnfm N0(int pos, const string &s);

parsed expr(const char *p) {
  parsed r = term(p);
  if (r.first == NULL)
    return r; // parse error
  while (*(r.first) == '+' || *(r.first) == '-') {
    const char *op = r.first;
    parsed l = term(op + 1);
    if (l.first == NULL)
      return l;

    if (*op == '+') {
      r.first = l.first;
      r.second = r.second + l.second;
    } else {
      r.first = l.first;
      r.second = r.second - l.second;
    }
  }
  return r;
}

parsed term(const char *p) {
  parsed r = fact(p);
  if (r.first == NULL)
    return r;
  while (*(r.first) == '*' || *(r.first) == '/') {
    const char *op = r.first;
    parsed l = fact(op + 1);
    if (l.first == NULL)
      return l;

    if (*op == '*') {
      r.first = l.first;
      r.second = r.second * l.second;
    } else {
      r.first = l.first;
      if (l.second == 0 || r.second % l.second != 0)
        return parsed(NULL, -1);
      r.second = int(r.second / l.second);
    }
  }
  return r;
}

inline parsed fact(const char *p) {
  if (*p == '(') {
    // new expression
    parsed tp = expr(p + 1);
    if (tp.first == NULL)
      return tp;
    return parsed(tp.first + 1, tp.second);
  }
  if (*p == '-') {
    // negative fact
    parsed tp = fact(p + 1);
    if (tp.first == NULL)
      return tp;
    tp.second *= -1;
    return tp;
  }
  if (isdigit(*p)) {
    // number
    int num = *p - '0';
    while (isdigit(*(++p))) {
      num *= 10;
      num += *p - '0';
    }
    return parsed(p, num);
  } else
    assert(0);
  return parsed(NULL, 0);
}

inline bool Eq(const string &s) {
  int pos = 0;
  bnfm r = Ex(pos, s);
  if (!r.first)
    return false;
  pos = r.second;
  if (pos >= s.length())
    return false;
  if (s[pos] != '=')
    return false;
  ++pos;
  r = Ex(pos, s);
  if (!r.first)
    return false;
  if (r.second < s.length())
    return false;
  return true;
}

bnfm Ex(int pos, const string &s) {
  if (pos >= s.length())
    return bnfm(false, pos);
  bnfm r = N0(pos, s);
  if (!r.first)
    return bnfm(false, r.second);
  pos = r.second;
  if (pos >= s.length())
    return bnfm(true, pos);
  while (s[pos] == '+' || s[pos] == '-' || s[pos] == '*' || s[pos] == '/') {
    bnfm r = N0(pos + 1, s);
    if (!r.first)
      return bnfm(false, r.second);
    pos = r.second;
    if (pos >= s.length())
      break;
  }
  return bnfm(true, pos);
}

bnfm N0(int pos, const string &s) {
  if (pos >= s.length())
    return bnfm(false, pos);
  if (!isdigit(s[pos]))
    return bnfm(false, pos + 1);
  if (s[pos] == '0') {
    if (pos + 1 < s.length()) {
      if (isdigit(s[pos + 1]))
        return bnfm(false, pos + 2);
    }
    return bnfm(true, pos + 1);
  } else {
    while (isdigit(s[pos])) {
      ++pos;
      if (pos >= s.length())
        break;
    }
    return bnfm(true, pos);
  }
}

bool Evaluate(const string &s) {
  string s1, s2;
  int i, j;
  for (i = 0; i < s.length(); ++i) {
    if (s[i] == '=')
      break;
    else
      s1 += s[i];
  }
  for (j = i + 1; j < s.length(); ++j) {
    s2 += s[j];
  }
  parsed p1 = expr(s1.c_str());
  parsed p2 = expr(s2.c_str());
  if (p1.first == NULL || p2.first == NULL)
    return false;
  if (p1.second == p2.second)
    return true;
  else
    return false;
}

bool Judge(const vector<string> &eqs) {

  for (int i = 0; i < eqs.size(); ++i) {
    if (eqs[i].find('.') == string::npos) {
      if (!Eq(eqs[i]))
        return false;
      if (!Evaluate(eqs[i]))
        return false;
    }
  }
  return true;
  /*
  const int di [] = {-1,0,1,0};
  const int dj [] = {0,1,0,-1};

  for(int i = 0; i < H; ++i){
    for(int j = 0; j < W; ++j){
      if( pzl[i+1][j+1] != '#' ){
        for(int l = 0; l < sizeof(di)/sizeof(*di); ++l){
          if( l == 1 || l == 2 ) continue;
          int ti = i + 1 + di[l]; int tj = j + 1 + dj[l];
          if( pzl[ti][tj] == '#' ){
            int dir = (l+2)%(sizeof(di)/sizeof(*di));
            ti = i+1+di[dir]; tj = j+1+dj[dir];
            string eq;
            eq += pzl[i+1][j+1];
            while(pzl[ti][tj]!='#'){
              eq += pzl[ti][tj]; ti += di[dir]; tj += dj[dir];
            }
            if( eq.length() >= 3 && eq.find('.') == string::npos ){
              if( !Eq(eq) ) return false;
              if( !Evaluate( eq ) ) return false;
            }
            eq.clear();
          }
        }
      }
    }
  }
  return true;
  */
}

bool operator<(const pair<int, int> &a, const pair<int, int> &b) {
  return a.first == b.first ? a.second < b.second : a.first < b.first;
}

bool dfs(int n, int now, const vector<pair<int, int>> &hole_pos,
         map<pair<int, int>, vector<pair<int, int>>> &meq,
         const vector<string> &eqs, bool vis[NMAX], char holes[NMAX], int H,
         int W, char pzl[][MAX]) {

  if (!Judge(eqs)) {
    return false;
  } else if (now == hole_pos.size()) {
    return true;
  }

  for (int i = 0; i < n; ++i) {
    if (!vis[i]) {
      const vector<pair<int, int>> &v = meq[hole_pos[now]];
      vector<string> teqs = eqs;
      // cout << "DOT POS=" << hole_pos[now].first << ' ' <<
      // hole_pos[now].second << " : ";
      for (int j = 0; j < v.size(); ++j) {
        // cout << v[j].first << ' ' << v[j].second << ',';
        teqs[v[j].first][v[j].second] = holes[i];
      }
      /*
      cout << endl;
      for(int j = 0; j < teqs.size(); ++j){
        cout << teqs[j] << endl;
      }
      cout << endl;
      */

      vis[i] = true;
      if (dfs(n, now + 1, hole_pos, meq, teqs, vis, holes, H, W, pzl))
        return true;
      vis[i] = false;
    }
  }
  return false;
}

int main(void) {
  while (true) {
    int H, W;
    char pzl[MAX][MAX];
    bool vis[NMAX] = {
        false,
    };
    vector<pair<int, int>> hole_pos;
    vector<string> eqs;
    map<pair<int, int>, vector<pair<int, int>>> meq;

    for (int i = 0; i < MAX; ++i)
      for (int j = 0; j < MAX; ++j)
        pzl[i][j] = '#';

    cin >> H >> W;
    if (H == 0 && W == 0)
      break;
    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        cin >> pzl[i + 1][j + 1];
        if (pzl[i + 1][j + 1] == '.') {
          hole_pos.push_back(make_pair(i + 1, j + 1));
        }
      }
    }

    int n, num = 0;
    cin >> n;
    int p[n];
    char holes[n];
    for (int i = 0; i < n; ++i) {
      char d;
      cin >> d;
      holes[num++] = d;
      p[i] = i;
    }

    const int di[] = {-1, 0, 1, 0};
    const int dj[] = {0, 1, 0, -1};

    for (int i = 0; i < H; ++i) {
      for (int j = 0; j < W; ++j) {
        if (pzl[i + 1][j + 1] != '#') {
          for (int l = 0; l < sizeof(di) / sizeof(*di); ++l) {
            if (l == 1 || l == 2)
              continue;
            int ti = i + 1 + di[l];
            int tj = j + 1 + dj[l];
            if (pzl[ti][tj] == '#') {
              int dir = (l + 2) % (sizeof(di) / sizeof(*di));
              ti = i + 1;
              tj = j + 1;
              string eq;
              vector<pair<int, int>> poss;
              vector<int> ats;
              while (pzl[ti][tj] != '#') {
                eq += pzl[ti][tj];
                if (pzl[ti][tj] == '.') {
                  poss.push_back(make_pair(ti, tj));
                  ats.push_back(eq.length() - 1);
                }
                ti += di[dir];
                tj += dj[dir];
              }
              if (eq.length() >= 3) {
                eqs.push_back(eq);
                // cout << "EQ : " << eq << endl;
                // cout << "DOT ATS : ";
                for (int i = 0; i < poss.size(); ++i) {
                  // cout << ats[i] << ' ';
                  meq[poss[i]].push_back(make_pair(eqs.size() - 1, ats[i]));
                }
                // cout << endl;
              }
            }
          }
        }
      }
    }

    if (dfs(n, 0, hole_pos, meq, eqs, vis, holes, H, W, pzl)) {
      cout << "Yes" << endl;
    } else {
      cout << "No" << endl;
    }
  }
  return 0;
}