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

#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
#define REP(i, j) for (int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for (int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
typedef pair<int, char *> P;

int ops[] = {'+', '-', '*'};
int bs[] = {'(', ')'};
int ds[] = {'0', '1'};
bool f;

P fact(char *p);
P term(char *p);
P expr(char *p);

P fact(char *p) {
  if (isdigit(*p)) {
    int t = *(p++) - '0';
    while (isdigit(*p))
      t = t * 2 + *(p++) - '0';
    if (t < 0 || t >= 1024)
      f = false;
    return P(t, p);
  } else if (*p == '(') {
    P r = expr(p + 1);
    if (*r.second != ')')
      exit(0); // 閉じ括弧が無いエラー
    if (r.first < 0 || r.first >= 1024)
      f = false;
    return P(r.first, r.second + 1);
  } else {
    exit(0); // 括弧でも数字でもないエラー
  }
}

P term(char *p) {
  P r = fact(p);
  while (*r.second == '*' || *r.second == '/') {
    char op = *r.second;
    int tmp = r.first;
    r = fact(r.second + 1);
    if (op == '*')
      r.first *= tmp;
    else
      r.first /= tmp;
    if (r.first < 0 || r.first >= 1024)
      f = false;
  }
  return r;
}

P expr(char *p) {
  P r = term(p);
  while (*r.second == '+' || *r.second == '-') {
    char op = *r.second;
    int tmp = r.first;
    r = term(r.second + 1);
    if (op == '+')
      r.first = tmp + r.first;
    else
      r.first = tmp - r.first;
    if (r.first < 0 || r.first >= 1024)
      f = false;
  }
  return r;
}

bool is_digit(string s) {
  if (s == "0" || s == "1")
    return true;
  return false;
}

bool is_operation(string s) {
  if (s == "+" || s == "-" || s == "*")
    return true;
  return false;
}

bool is_number(string s) {
  if (is_digit(s) ||
      ((int)s.length() >= 2 && is_number(s.substr(0, (int)s.length() - 1)) &&
       is_digit(s.substr(s.length() - 1))))
    return true;
  return false;
}

bool check(string s) {
  int cnt = 0;
  REP(i, s.length()) {
    if (s[i] == '(')
      ++cnt;
    if (s[i] == ')')
      --cnt;
    if (cnt < 0)
      return false;
  }
  return cnt == 0;
}

bool is_expression(string s);

bool is_inner_expression(string s) {
  FOR(i, 1, (int)s.length() - 1) {
    if (is_operation(s.substr(i, 1)) && is_expression(s.substr(0, i)) &&
        is_expression(s.substr(i + 1))) {
      return true;
    }
  }
  return false;
}

bool is_expression(string s) {
  if ((int)s.length() >= 2 && s[0] == '(' && s[(int)s.length() - 1] == ')' &&
      check(s.substr(1, (int)s.length() - 2))) {
    bool res = is_inner_expression(s.substr(1, (int)s.length() - 2));
    return res;
  }
  if (is_number(s)) {
    return true;
  }
  FOR(i, 1, (int)s.length() - 1) {
    if (is_operation(s.substr(i, 1)) && is_expression(s.substr(0, i)) &&
        is_expression(s.substr(i + 1))) {
      return true;
    }
  }
  return false;
}

bool is_invalid(char *s) {
  int sl = strlen(s);
  if (s[0] == '+' || s[0] == '-' || s[0] == '*' || s[0] == ')')
    return true;
  if (s[sl - 1] == '+' || s[sl - 1] == '-' || s[sl - 1] == '*' ||
      s[sl - 1] == '(')
    return true;
  FOR(i, 1, sl - 1) {
    if (s[i] == '+' || s[i] == '-' || s[i] == '*') {
      if (s[i - 1] != '.' && s[i - 1] != ')' && !isdigit(s[i - 1]))
        return true;
      if (s[i + 1] != '.' && s[i + 1] != '(' && !isdigit(s[i + 1]))
        return true;
    }
    if (s[i] == ')') {
      if (s[i - 1] != '.' && !isdigit(s[i - 1]) && s[i - 1] != ')')
        return true;
      if (s[i + 1] != '.' && s[i + 1] != ')' && s[i + 1] != '+' &&
          s[i + 1] != '-' && s[i + 1] != '*')
        return true;
    }
    if (s[i] == '(') {
      if (s[i + 1] != '.' && !isdigit(s[i + 1]) && s[i + 1] != '(')
        return true;
      if (s[i - 1] != '.' && s[i - 1] != '(' && s[i - 1] != '+' &&
          s[i - 1] != '-' && s[i - 1] != '*')
        return true;
    }
  }
  return false;
}

int solve(int cnt, vector<int> &v, char *s) {
  // cout <<"! " <<s <<", " <<is_invalid(s) <<endl;
  if (is_invalid(s))
    return -1;
  if (cnt >= (int)v.size()) {
    if (!is_expression(s))
      return -1;
    f = true;
    int res = expr(s).first;
    // cout <<"!! " <<res <<", " <<f <<endl;
    return f && res >= 0 && res < 1024 ? res : -1;
  }
  if (is_invalid(s))
    return -1;
  int res = -1, sl = strlen(s);
  if (v[cnt] != 0 && v[cnt] != sl - 1) {
    REP(i, 3) {
      s[v[cnt]] = ops[i];
      res = max(res, solve(cnt + 1, v, s));
      s[v[cnt]] = '.';
    }
  }
  REP(i, 2) {
    s[v[cnt]] = bs[i];
    res = max(res, solve(cnt + 1, v, s));
    s[v[cnt]] = '.';
  }
  REP(i, 2) {
    s[v[cnt]] = ds[i];
    res = max(res, solve(cnt + 1, v, s));
    s[v[cnt]] = '.';
  }
  return res;
}

int main() {
  char s[110];
  cin >> s;
  int sl = strlen(s);
  vector<int> v;
  REP(i, sl) if (s[i] == '.') v.push_back(i);
  cout << solve(0, v, s) << endl;
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
#define REP(i, j) for (int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for (int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
typedef pair<int, char *> P;

int ops[] = {'+', '-', '*'};
int bs[] = {'(', ')'};
int ds[] = {'0', '1'};

P fact(char *p);
P term(char *p);
P expr(char *p);

P fact(char *p) {
  if (isdigit(*p)) {
    int t = *(p++) - '0';
    while (isdigit(*p))
      t = t * 2 + *(p++) - '0';
    return P(t, p);
  } else if (*p == '(') {
    P r = expr(p + 1);
    if (*r.second != ')')
      exit(0); // 閉じ括弧が無いエラー
    return P(r.first, r.second + 1);
  } else {
    exit(0); // 括弧でも数字でもないエラー
  }
}

P term(char *p) {
  P r = fact(p);
  while (*r.second == '*' || *r.second == '/') {
    char op = *r.second;
    int tmp = r.first;
    r = fact(r.second + 1);
    if (op == '*')
      r.first *= tmp;
    else
      r.first /= tmp;
  }
  return r;
}

P expr(char *p) {
  P r = term(p);
  while (*r.second == '+' || *r.second == '-') {
    char op = *r.second;
    int tmp = r.first;
    r = term(r.second + 1);
    if (op == '+')
      r.first = tmp + r.first;
    else
      r.first = tmp - r.first;
  }
  return r;
}

bool is_digit(string s) {
  if (s == "0" || s == "1")
    return true;
  return false;
}

bool is_operation(string s) {
  if (s == "+" || s == "-" || s == "*")
    return true;
  return false;
}

bool is_number(string s) {
  if (is_digit(s) ||
      ((int)s.length() >= 2 && is_number(s.substr(0, (int)s.length() - 1)) &&
       is_digit(s.substr(s.length() - 1))))
    return true;
  return false;
}

bool check(string s) {
  int cnt = 0;
  REP(i, s.length()) {
    if (s[i] == '(')
      ++cnt;
    if (s[i] == ')')
      --cnt;
    if (cnt < 0)
      return false;
  }
  return cnt == 0;
}

bool is_expression(string s);

bool is_inner_expression(string s) {
  // cout <<"inner_exp " <<s <<endl;
  FOR(i, 1, (int)s.length() - 1) {
    // cout <<"left " <<s.substr(0, i) <<", right " <<s.substr(i + 1) <<endl;
    if (is_operation(s.substr(i, 1)) && is_expression(s.substr(0, i)) &&
        is_expression(s.substr(i + 1))) {
      // cout <<"true" <<endl;
      return true;
    }
  }
  // cout <<"false" <<endl;
  return false;
}

bool is_expression(string s) {
  // cout <<"exp " <<s <<endl;
  if ((int)s.length() >= 2 && s[0] == '(' && s[(int)s.length() - 1] == ')' &&
      check(s.substr(1, (int)s.length() - 2))) {
    bool res = is_inner_expression(s.substr(1, (int)s.length() - 2));
    // cout <<(res ? "true" : "false") <<endl;
    return res;
  }
  if (is_number(s)) {
    // cout <<"true" <<endl;
    return true;
  }
  FOR(i, 1, (int)s.length() - 1) {
    if (is_operation(s.substr(i, 1)) && is_expression(s.substr(0, i)) &&
        is_expression(s.substr(i + 1))) {
      // cout <<"true" <<endl;
      return true;
    }
  }
  // cout <<"false" <<endl;
  return false;
}

int solve(int cnt, vector<int> &v, char *s) {
  // cout <<"! " <<s <<", " <<is_expression(s) <<endl;
  if (cnt >= (int)v.size()) {
    if (!is_expression(s))
      return -1;
    int res = expr(s).first;
    return res >= 0 && res < 1024 ? res : -1;
  }
  int res = -1, sl = strlen(s);
  if (v[cnt] != 0 && v[cnt] != sl - 1) {
    int l = v[cnt] - 1, r = v[cnt] + 1;
    REP(i, 3) {
      s[v[cnt]] = ops[i];
      res = max(res, solve(cnt + 1, v, s));
      s[v[cnt]] = '.';
    }
  }
  REP(i, 2) {
    s[v[cnt]] = bs[i];
    res = max(res, solve(cnt + 1, v, s));
    s[v[cnt]] = '.';
  }
  REP(i, 2) {
    s[v[cnt]] = ds[i];
    res = max(res, solve(cnt + 1, v, s));
    s[v[cnt]] = '.';
  }
  return res;
}

int main() {
  char s[110];
  cin >> s;
  int sl = strlen(s);
  vector<int> v;
  REP(i, sl) if (s[i] == '.') v.push_back(i);
  cout << solve(0, v, s) << endl;
  return 0;
}