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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a, b) (a < b ? (a = b, 1) : 0)
#define chmin(a, b) (a > b ? (a = b, 1) : 0)
#define valid(y, x, h, w) (0 <= y && y < h && 0 <= x && x < w)
typedef long long ll;
typedef pair<int, int> pii;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;

char str[1010];
typedef int Int;

Int term(int &i);
Int fact(int &i);

Int exp(int &i) {
  Int p = term(i);
  while (str[i] == '+' || str[i] == '-') {
    char c = str[i++];
    if (c == '+') {
      Int a = term(i);
      p += a;
    } else
      p -= term(i);
  }
  return p;
}

Int term(int &i) {
  Int p = fact(i);
  while (str[i] == '*' || str[i] == '/') {
    if (str[i++] == '*') {
      p *= fact(i);
    } else {
      int r = fact(i);
      if (r == 0)
        throw 0;
      if (p % r == 0)
        p /= r;
      else
        throw 0;
    }
  }
  return p;
}

Int fact(int &i) {
  Int p = 0;
  if (!isdigit(str[i]))
    throw 0;
  while (isdigit(str[i])) {
    p *= 10;
    p += str[i] - '0';
    i++;
  }
  return p;
}

Int parse() {
  int id = 0;
  Int res = exp(id);
  if (str[id])
    throw 0;
  return res;
}

inline bool isoperator(char c) {
  return c == '+' || c == '-' || c == '*' || c == '/' || c == '=';
}

bool check(char *s) {
  try {
    int n = strlen(s);
    int pos = -1;
    REP(i, strlen(s)) if (s[i] == '=') pos = i;
    if (pos == -1 || pos == 0 || pos == n - 1)
      return 0;
    for (int i = 0; i < pos; ++i)
      str[i] = s[i];
    str[pos] = 0;
    Int a = parse();
    for (int i = pos + 1; i < n; ++i)
      str[i - pos - 1] = s[i];
    str[n - pos - 1] = 0;
    Int b = parse();
    if (a == b)
      return 1;
    else
      return 0;
  } catch (int a) {
    return 0;
  }
}

char a[10][10];
char b[10];

char eq[100][11];

int h, w;

bool inserted[10][10];

pii pos[100];
int posNum;
int eqNum;
bool visited[10][10][2];

vector<pii> ididx[10][10];
int dotNum[100];

bool bfs(int y, int x, int dy, int dx) {
  char s[11];
  int idx = 0;
  vector<pii> v;
  vector<int> id;
  while (valid(y, x, h, w)) {
    visited[y][x][dy] = 1;
    if (a[y][x] == '#')
      break;
    if (a[y][x] == '.') {
      v.push_back(pii(y, x));
      id.push_back(idx);
    }
    s[idx++] = a[y][x];
    y += dy;
    x += dx;
  }
  if (idx >= 3) {
    s[idx] = 0;
    if (v.size() == 0 && !check(s))
      return 0;
    dotNum[eqNum] = v.size();
    strcpy(eq[eqNum], s);
    REP(i, v.size()) {
      int y = v[i].first, x = v[i].second;
      ididx[y][x].push_back(pii(eqNum, id[i]));
      if (!inserted[y][x]) {
        pos[posNum++] = pii(y, x);
        inserted[y][x] = 1;
      }
    }
    eqNum++;
  }
  return 1;
}

bool checkOp(int id, int idx) {
  int n = strlen(eq[id]);
  if (idx == 0 || idx == n - 1)
    return 1;
  if (isoperator(eq[id][idx - 1]))
    return 1;
  if (isoperator(eq[id][idx + 1]))
    return 1;
  return 0;
}

const int dy[4] = {-1, 0, 1, 0};
const int dx[4] = {0, 1, 0, -1};

bool isNumOnly(int now, int y, int x) {
  FOR(it, ididx[y][x]) {
    int id = it->first;
    int idx = it->second;
    if (checkOp(id, idx))
      return 1;
  }
  return 0;
}

bool isHead(int now, int y, int x) {
  FOR(it, ididx[y][x]) {
    int id = it->first;
    int idx = it->second;
    if (idx == 0 || isoperator(eq[id][idx - 1]))
      return 1;
  }
  return 0;
}

bool numOnly[100];

int n;

bool dfs(int S, int now) {
  if (now == posNum)
    return 1;
  int y = pos[now].first;
  int x = pos[now].second;
  FOR(it, ididx[y][x]) { dotNum[it->first]--; }

  REP(i, n) {
    if (S >> i & 1)
      continue;
    if (!isdigit(b[i]) && isNumOnly(now, y, x))
      continue;
    // cout << y << " " << x << " " << now << " " << b[i] << endl;
    // if (b[i] == '0' && isHead(now,y,x)) continue;
    bool f = 1;
    FOR(it, ididx[y][x]) {
      int id = it->first;
      int idx = it->second;
      eq[id][idx] = b[i];
      if (dotNum[id] == 0) {
        f &= check(eq[id]);
      }
    }
    if (f) {
      if (dfs(S | 1 << i, now + 1))
        return 1;
    }
  }
  FOR(it, ididx[y][x]) {
    eq[it->first][it->second] = '.';
    dotNum[it->first]++;
  }
  return 0;
}

int main() {
  while (cin >> h >> w, h || w) {
    REP(i, h) REP(j, w) { cin >> a[i][j]; }
    cin >> n;
    REP(i, n) cin >> b[i];
    memset(inserted, 0, sizeof(inserted));
    memset(visited, 0, sizeof(visited));
    posNum = 0, eqNum = 0;
    REP(i, h) REP(j, w) ididx[i][j].clear();
    memset(dotNum, 0, sizeof(dotNum));
    REP(i, h) {
      REP(j, w) {
        if (a[i][j] == '#')
          continue;
        if (!visited[i][j][1])
          bfs(i, j, 1, 0);
        if (!visited[i][j][0])
          bfs(i, j, 0, 1);
      }
    }
    memset(numOnly, 0, sizeof(numOnly));
    REP(i, posNum) {
      FOR(it, ididx[pos[i].first][pos[i].second]) {
        numOnly[i] = checkOp(it->first, it->second);
      }
    }
    // REP(i,eqNum) cout << eq[i] << endl;
    // REP(i,posNum) {
    //   cout << numOnly[i] << endl;
    //   cout << pos[i].first << " " << pos[i].second << endl;
    //   FOR(it, ididx[pos[i].first][pos[i].second]) {
    //     cout << it->first << ":" << it->second << endl;
    //   }cout << endl;
    // }
    cout << (dfs(0, 0) ? "Yes" : "No") << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <valarray>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a, b) (a < b ? (a = b, 1) : 0)
#define chmin(a, b) (a > b ? (a = b, 1) : 0)
#define valid(y, x, h, w) (0 <= y && y < h && 0 <= x && x < w)
typedef long long ll;
typedef pair<int, int> pii;
const int INF = 1 << 29;
const double PI = acos(-1);
const double EPS = 1e-8;

char str[1010];
typedef int Int;

Int term(int &i);
Int fact(int &i);

Int exp(int &i) {
  Int p = term(i);
  while (str[i] == '+' || str[i] == '-') {
    char c = str[i++];
    if (c == '+') {
      Int a = term(i);
      p += a;
    } else
      p -= term(i);
  }
  return p;
}

Int term(int &i) {
  Int p = fact(i);
  while (str[i] == '*' || str[i] == '/') {
    if (str[i++] == '*') {
      p *= fact(i);
    } else {
      int r = fact(i);
      if (r == 0)
        throw 0;
      if (p % r == 0)
        p /= r;
      else
        throw 0;
    }
  }
  return p;
}

Int fact(int &i) {
  Int p = 0;
  if (!isdigit(str[i]))
    throw 0;
  while (isdigit(str[i])) {
    p *= 10;
    p += str[i] - '0';
    i++;
  }
  return p;
}

Int parse() {
  int id = 0;
  Int res = exp(id);
  if (str[id])
    throw 0;
  return res;
}

inline bool isoperator(char c) {
  return c == '+' || c == '-' || c == '*' || c == '/' || c == '=';
}

bool check(char *s) {
  try {
    int n = strlen(s);
    int pos = -1;
    REP(i, strlen(s)) if (s[i] == '=') pos = i;
    if (pos == -1 || pos == 0 || pos == n - 1)
      return 0;
    for (int i = 0; i < pos; ++i)
      str[i] = s[i];
    str[pos] = 0;
    Int a = parse();
    for (int i = pos + 1; i < n; ++i)
      str[i - pos - 1] = s[i];
    str[n - pos - 1] = 0;
    Int b = parse();
    if (a == b)
      return 1;
    else
      return 0;
  } catch (int a) {
    return 0;
  }
}

char a[10][10];
char b[10];

char eq[100][11];

int h, w;

bool inserted[10][10];

pii pos[100];
int posNum;
int eqNum;
bool visited[10][10][2];

vector<pii> ididx[10][10];
int dotNum[100];

bool bfs(int y, int x, int dy, int dx) {
  char s[11];
  int idx = 0;
  vector<pii> v;
  vector<int> id;
  while (valid(y, x, h, w)) {
    visited[y][x][dy] = 1;
    if (a[y][x] == '#')
      break;
    if (a[y][x] == '.') {
      v.push_back(pii(y, x));
      id.push_back(idx);
    }
    s[idx++] = a[y][x];
    y += dy;
    x += dx;
  }
  if (idx >= 2) {
    s[idx] = 0;
    if (v.size() == 0 && !check(s))
      return 0;
    dotNum[eqNum] = v.size();
    strcpy(eq[eqNum], s);
    REP(i, v.size()) {
      int y = v[i].first, x = v[i].second;
      ididx[y][x].push_back(pii(eqNum, id[i]));
      if (!inserted[y][x]) {
        pos[posNum++] = pii(y, x);
        inserted[y][x] = 1;
      }
    }
    eqNum++;
  }
  return 1;
}

bool checkOp(int id, int idx) {
  int n = strlen(eq[id]);
  if (idx && isoperator(eq[id][idx - 1]))
    return 1;
  if (idx + 1 < n && isoperator(eq[id][idx + 1]))
    return 1;
  return 0;
}

bool numOnly[100];
int n;

bool dfs(int S, int now) {
  if (now == posNum)
    return 1;
  int y = pos[now].first;
  int x = pos[now].second;
  FOR(it, ididx[y][x]) { dotNum[it->first]--; }
  REP(i, n) {
    if (S >> i & 1)
      continue;
    if (!isdigit(b[i]) && numOnly[now])
      continue;
    bool f = 1;
    FOR(it, ididx[y][x]) {
      int id = it->first;
      int idx = it->second;
      eq[id][idx] = b[i];
      if (dotNum[id] == 0) {
        f &= check(eq[id]);
      }
    }
    if (f) {
      if (dfs(S | 1 << i, now + 1))
        return 1;
    }
  }
  FOR(it, ididx[y][x]) {
    eq[it->first][it->second] = '.';
    dotNum[it->first]++;
  }
  return 0;
}

int main() {
  while (cin >> h >> w, h || w) {
    REP(i, h) REP(j, w) { cin >> a[i][j]; }
    cin >> n;
    REP(i, n) cin >> b[i];
    memset(inserted, 0, sizeof(inserted));
    memset(visited, 0, sizeof(visited));
    posNum = 0, eqNum = 0;
    REP(i, h) REP(j, w) ididx[i][j].clear();
    memset(dotNum, 0, sizeof(dotNum));
    REP(i, h) {
      REP(j, w) {
        if (a[i][j] == '#')
          continue;
        if (!visited[i][j][1])
          bfs(i, j, 1, 0);
        if (!visited[i][j][0])
          bfs(i, j, 0, 1);
      }
    }
    memset(numOnly, 0, sizeof(numOnly));
    REP(i, posNum) {
      FOR(it, ididx[pos[i].first][pos[i].second]) {
        numOnly[i] = checkOp(it->first, it->second);
      }
    }
    int noEqNum = 0;
    REP(i, eqNum) {
      bool f = 0;
      REP(j, strlen(eq[i])) f |= (eq[i][j] == '=');
      if (!f)
        noEqNum++;
    }
    int beqNum = 0;
    REP(i, n) if (b[i] == '=') beqNum++;
    if ((noEqNum + 1) / 2 > beqNum) {
      cout << "No" << endl;
      continue;
    }
    // REP(i,eqNum) cout << eq[i] << endl;
    // REP(i,posNum) {
    //   cout << numOnly[i] << endl;
    //   cout << pos[i].first << " " << pos[i].second << endl;
    //   FOR(it, ididx[pos[i].first][pos[i].second]) {
    //     cout << it->first << ":" << it->second << endl;
    //   }cout << endl;
    // }
    cout << (dfs(0, 0) ? "Yes" : "No") << endl;
  }
}