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

// AOJ 1022
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#define value first
#define p second
using namespace std;
typedef pair<int, int> result;

const int OutOfIntExc = 1, NegIntExc = 2, NotEquationExc = 3, NotNumExc = 4,
          LackNumExc = 5, IterExceedExc = 6;

result equation(const string &s, int p = 0);
result expression(const string &s, int p = 0);
result factor(const string &s, int p = 0);
result term(const string &s, int p = 0);

result equation(const string &s, int p) {
  //  cout << "? " << s << " ";
  if (s[p] == '=') {
    throw NotEquationExc;
  }
  result r = expression(s, p);
  if (s[r.p] != '=') {
    throw NotEquationExc;
  }

  r.p++; // skip '=';
  result t = expression(s, r.p);
  t.value = (int)(r.value == t.value);

  //  cout << (t.value ? "T" : "F") << endl;

  return t;
}

result expression(const string &s, int p) {
  result r = factor(s, p);
  while (s[r.p] == '+' or s[r.p] == '-') {
    result r_ = factor(s, r.p + 1);
    r.value += (s[r.p] == '+' ? r_.value : -r_.value);
    if (r.value < 0) {
      throw NegIntExc;
    }
    r.p = r_.p;
  }
  return r;
}

result factor(const string &s, int p) {
  result r = term(s, p);
  while (s[r.p] == '*' or s[r.p] == '/') {
    result r_ = term(s, r.p + 1);
    if (s[r.p] == '*') {
      r.value *= r_.value;
    } else {
      if (r_.value == 0 or r.value % r_.value != 0) {
        throw OutOfIntExc;
      }
      r.value /= r_.value;
    }
    r.p = r_.p;
  }
  return r;
}

result term(const string &s, int p) {
  if (not isdigit(s[p])) {
    throw LackNumExc;
  }
  int value = 0;
  bool flag = false;

  while (isdigit(s[p])) {
    if (flag and value == 0) {
      throw NotNumExc;
    }
    flag = true;
    value = value * 10 + (s[p++] - '0');
  }
  return result(value, p);
}

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
int H, W, n;
const int HMAX = 200, WMAX = 200, NMAX = 200;
char TABLE[HMAX][WMAX];
bool PRINTED[HMAX][WMAX], HBEGIN[HMAX][WMAX], VBEGIN[HMAX][WMAX];
char BLOCK[NMAX];

bool legal(int x, int y) { return 0 <= x and x < W and 0 <= y and y < H; }

vector<pair<int, int>> blanks;

void fill_blank() {
  int i = 0;
  REP(i, n) {
    int x = blanks[i].first, y = blanks[i].second;
    TABLE[x][y] = BLOCK[i];
  }
}

string getv(int x, int y) {
  string str;
  while (legal(x, y) and TABLE[x][y] != '#') {
    str.push_back(TABLE[x][y]);
    y++;
  }
  return str;
}

string geth(int x, int y) {
  string str;
  while (legal(x, y) and TABLE[x][y] != '#') {
    str.push_back(TABLE[x][y]);
    x++;
  }
  return str;
}

bool is_operand(char c) {
  return c == '=' or c == '+' or c == '-' or c == '*' or c == '/';
}

bool is_illegal_operand() {
  REP(y, H) REP(x, W) {
    if (PRINTED[x][y])
      continue;
    if (not is_operand(TABLE[x][y]))
      continue;
    const int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0};
    REP(i, 4) {
      int nx = x + dx[i], ny = y + dy[i];
      if (legal(nx, ny) and is_operand(TABLE[nx][ny])) {
        return true;
      }
    }
  }

  REP(y, H) REP(x, W) {
    if ((VBEGIN[x][y] or HBEGIN[x][y]) and is_operand(TABLE[x][y])) {
      return true;
    }
  }
  return false;
}

int hbadx, hbady, vbadx, vbady;
bool hbadflag, vbadflag;
string hbadeq, vbadeq;

bool solved() {
  if (hbadflag and geth(hbadx, hbady) == hbadeq)
    return false;
  if (vbadflag and geth(vbadx, vbady) == vbadeq)
    return false;
  REP(y, H) REP(x, W) {
    if (not HBEGIN[x][y])
      continue;
    string eq = geth(x, y);
    try {
      result e = equation(eq);
      if (e.value == 0) {
        hbadflag = true;
        hbadx = x, hbady = y;
        hbadeq = eq;
        return false;
      }
    } catch (int ex) {
      hbadflag = true;
      hbadx = x, hbady = y;
      hbadeq = eq;
      return false;
    }
  }

  REP(y, H) REP(x, W) {
    if (not VBEGIN[x][y])
      continue;
    string eq = getv(x, y);
    try {
      result e = equation(eq);
      if (e.value == 0) {
        vbadflag = true;
        vbadx = x, vbady = y;
        vbadeq = eq;
        return false;
      }
    } catch (int ex) {
      vbadflag = true;
      vbadx = x, vbady = y;
      vbadeq = eq;
      return false;
    }
  }
  return true;
}

bool solve() {
  sort(BLOCK, BLOCK + n);
  do {
    fill_blank();
    if (is_illegal_operand())
      continue;
    if (solved()) {
      return true;
    }
  } while (next_permutation(BLOCK, BLOCK + n));
}

void init() {
  blanks.clear();
  REP(y, H) REP(x, W) {
    hbadflag = vbadflag = false;
    PRINTED[x][y] = false;
    HBEGIN[x][y] = false;
    VBEGIN[x][y] = false;
  }
}

int main() {
  while (cin >> H >> W and H + W) {
    init();

    REP(y, H) {
      string row;
      cin >> row;
      REP(x, W) {
        TABLE[x][y] = row[x];
        PRINTED[x][y] = row[x] != '.';
        if (row[x] == '.') {
          blanks.push_back(make_pair(x, y));
        }
      }
    }

    REP(y, H) REP(x, W) {
      if (TABLE[x][y] != '#' and legal(x + 1, y) and TABLE[x + 1][y] != '#' and
          (!legal(x - 1, y) or TABLE[x - 1][y] == '#')) {
        HBEGIN[x][y] = true;
      }
      if (TABLE[x][y] != '#' and legal(x, y + 1) and TABLE[x][y + 1] != '#' and
          (!legal(x, y - 1) or TABLE[x][y - 1] == '#')) {
        VBEGIN[x][y] = true;
      }
    }

    cin >> n;
    REP(i, n) { cin >> BLOCK[i]; }

    cout << (solve() ? "Yes" : "No") << endl;
  }
}

Error: TLE

Fixed submission:

// AOJ 1022
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#define value first
#define p second
using namespace std;
typedef pair<int, int> result;

const int OutOfIntExc = 1, NegIntExc = 2, NotEquationExc = 3, NotNumExc = 4,
          LackNumExc = 5, IterExceedExc = 6;

result equation(const string &s, int p = 0);
result expression(const string &s, int p = 0);
result factor(const string &s, int p = 0);
result term(const string &s, int p = 0);

int BADHX, BADHY, BADVX, BADVY;
string BADHEQ, BADVEQ;

result equation(const string &s, int p) {
  if (s[p] == '=') {
    throw NotEquationExc;
  }
  result r = expression(s, p);
  if (s[r.p] != '=') {
    throw NotEquationExc;
  }

  r.p++; // skip '=';
  result t = expression(s, r.p);
  t.value = (int)(r.value == t.value);

  return t;
}

result expression(const string &s, int p) {
  result r = factor(s, p);
  while (s[r.p] == '+' or s[r.p] == '-') {
    result r_ = factor(s, r.p + 1);
    r.value += (s[r.p] == '+' ? r_.value : -r_.value);
    if (r.value < 0) {
      throw NegIntExc;
    }
    r.p = r_.p;
  }
  return r;
}

result factor(const string &s, int p) {
  result r = term(s, p);
  while (s[r.p] == '*' or s[r.p] == '/') {
    result r_ = term(s, r.p + 1);
    if (s[r.p] == '*') {
      r.value *= r_.value;
    } else {
      if (r_.value == 0 or r.value % r_.value != 0) {
        throw OutOfIntExc;
      }
      r.value /= r_.value;
    }
    r.p = r_.p;
  }
  return r;
}

result term(const string &s, int p) {
  if (not isdigit(s[p])) {
    throw LackNumExc;
  }
  int value = 0;
  bool flag = false;

  while (isdigit(s[p])) {
    if (flag and value == 0) {
      throw NotNumExc;
    }
    flag = true;
    value = value * 10 + (s[p++] - '0');
  }
  return result(value, p);
}

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
int H, W, n;
const int HMAX = 200, WMAX = 200, NMAX = 200;
char TABLE[HMAX][WMAX];
bool PRINTED[HMAX][WMAX], HBEGIN[HMAX][WMAX], VBEGIN[HMAX][WMAX];
char BLOCK[NMAX];

bool legal(int x, int y) { return 0 <= x and x < W and 0 <= y and y < H; }

void fill_blank() {
  int i = 0;
  REP(y, H) REP(x, W) {
    if (i == n)
      return;
    if (not PRINTED[x][y]) {
      TABLE[x][y] = BLOCK[i++];
    }
  }
}

string getv(int x, int y) {
  if (x == -1 and y == -1)
    return "";
  string str;
  while (legal(x, y) and TABLE[x][y] != '#') {
    str.push_back(TABLE[x][y]);
    y++;
  }
  return str;
}

string geth(int x, int y) {
  if (x == -1 and y == -1)
    return "";
  string str;
  while (legal(x, y) and TABLE[x][y] != '#') {
    str.push_back(TABLE[x][y]);
    x++;
  }
  return str;
}

bool is_operand(char c) {
  return c == '=' or c == '+' or c == '-' or c == '*' or c == '/';
}

bool is_illegal_operand() {
  REP(y, H) REP(x, W) {
    if (PRINTED[x][y])
      continue;
    if (not is_operand(TABLE[x][y]))
      continue;
    const int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0};
    REP(i, 4) {
      int nx = x + dx[i], ny = y + dy[i];
      if (legal(nx, ny) and is_operand(TABLE[nx][ny])) {
        return true;
      }
    }
  }

  REP(y, H) REP(x, W) {
    if ((VBEGIN[x][y] or HBEGIN[x][y]) and is_operand(TABLE[x][y])) {
      return true;
    }
  }
  return false;
}

bool solved() {
  REP(y, H) REP(x, W) {
    if (not HBEGIN[x][y])
      continue;
    string eq = geth(x, y);
    try {
      result e = equation(eq);
      if (e.value == 0) {
        BADHX = x, BADHY = y;
        BADHEQ = eq;
        return false;
      }
    } catch (int ex) {
      BADHX = x, BADHY = y;
      BADHEQ = eq;
      return false;
    }
  }

  REP(y, H) REP(x, W) {
    if (not VBEGIN[x][y])
      continue;
    string eq = getv(x, y);
    try {
      result e = equation(eq);
      if (e.value == 0) {
        BADVX = x, BADVY = y;
        BADVEQ = eq;
        return false;
      }
    } catch (int ex) {
      BADVX = x, BADVY = y;
      BADVEQ = eq;
      return false;
    }
  }
  return true;
}

int factorial(int x) {
  int sum = 1;
  for (int i = 1; i <= x; i++) {
    sum *= i;
  }
  return sum;
}

bool nextperm() {
  while (next_permutation(BLOCK, BLOCK + n)) {
    fill_blank();
    if (BADHEQ != geth(BADHX, BADHY) and BADVEQ != getv(BADVX, BADVY)) {
      //     cout << "o" << BADHEQ << " " << geth(BADHX,BADHY) << " " << BADVEQ
      //     << " " << getv(BADVX, BADVY) << endl;
      return true;
    } /* else {
       cout << "x" << BADHEQ << " " << geth(BADHX,BADHY) << " " << BADVEQ << " "
     << getv(BADVX, BADVY) << endl;
     }*/
  }
  return false;
}

bool solve() {
  sort(BLOCK, BLOCK + n);
  //  int consid = 0;
  do {
    //    if (BADHEQ == geth(BADHX, BADHY)) continue;
    //    if (BADVEQ == getv(BADVX, BADVY)) continue;
    if (is_illegal_operand())
      continue;
    if (solved()) {
      //      cout << consid << " / " << factorial(n) << endl;
      return true;
    } /* else {
       REP(y, H) {
         REP(x, W) {
           cout << TABLE[x][y];
         }
         cout << endl;
       }
       cout << endl;
       consid++;
     }*/
  } while (nextperm());
  //  cout << consid << " / " << factorial(n) << endl;
  return false;
}

void init() {
  BADHX = BADHY = BADVX = BADVY = -1;
  BADHEQ = BADVEQ = "No";
  REP(y, H) REP(x, W) {
    PRINTED[x][y] = false;
    HBEGIN[x][y] = false;
    VBEGIN[x][y] = false;
  }
}

int main() {
  while (cin >> H >> W and H + W) {
    init();

    REP(y, H) {
      string row;
      cin >> row;
      REP(x, W) {
        TABLE[x][y] = row[x];
        PRINTED[x][y] = row[x] != '.';
      }
    }

    REP(y, H) REP(x, W) {
      if (TABLE[x][y] != '#' and legal(x + 1, y) and TABLE[x + 1][y] != '#' and
          (!legal(x - 1, y) or TABLE[x - 1][y] == '#')) {
        HBEGIN[x][y] = true;
      }
      if (TABLE[x][y] != '#' and legal(x, y + 1) and TABLE[x][y + 1] != '#' and
          (!legal(x, y - 1) or TABLE[x][y - 1] == '#')) {
        VBEGIN[x][y] = true;
      }
    }

    cin >> n;
    REP(i, n) { cin >> BLOCK[i]; }

    cout << (solve() ? "Yes" : "No") << endl;
  }
}