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

#pragma GCC optimize "O3"

#define F first
#define S second
#define ALL(x) x.begin(), x.end()

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<LL, int> PLI;

constexpr int N = 19, INF = INT_MAX / 2;
const int di[9] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};
const int dj[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};

int h, w, chts, digs, idigs[N], jdigs[N], ichts[N * N], jchts[N * N];
LL pw10[N];
char t[N][N];
bool poss[N][N];
map<PLI, int> dp;

inline bool in_border(int i, int j) {
  return i >= 0 && j >= 0 && i < h && j < w;
}
PLI init() {
  chts = digs = 0;
  dp.clear();
  for (int i = 0; i < h; ++i) {
    scanf("%s", t[i]);
    fill_n(poss[i], w, false);
  }
  PLI cur = {0, 0};
  for (int i = 0; i < h; ++i)
    for (int j = 0; j < w; ++j)
      if (isdigit(t[i][j])) {
        idigs[digs] = i;
        jdigs[digs] = j;
        cur.F += pw10[digs] * (t[i][j] - '0');
        ++digs;
        for (int k = 0; k < 9; ++k) {
          int ni = i + di[k], nj = j + dj[k];
          if (in_border(ni, nj) && t[ni][nj] != '.')
            poss[ni][nj] = true;
        }
      }
  for (int i = 0; i < h; ++i)
    for (int j = 0; j < w; ++j)
      if (poss[i][j]) {
        ichts[chts] = i;
        jchts[chts] = j;
        ++chts;
      }
  return cur;
}
inline bool is_near(int i, int j) {
  return abs(idigs[i] - ichts[j]) <= 1 && abs(jdigs[i] - jchts[j]) <= 1;
}
inline bool not_enough(PLI cur) {
  for (int i = 0; i < digs; ++i) {
    int tcnt = 0;
    for (int j = cur.S; j < chts; ++j)
      if (is_near(i, j))
        ++tcnt;
    if (tcnt < cur.F % pw10[i + 1] / pw10[i])
      return true;
  }
  return false;
}
bool can_put(PLI cur) {
  for (int i = 0; i < digs; ++i)
    if (is_near(i, cur.S) && cur.F % pw10[i + 1] / pw10[i] == 0)
      return false;
  return true;
}
LL process(PLI cur) {
  for (int i = 0; i < digs; ++i)
    if (is_near(i, cur.S))
      cur.F -= pw10[i];
  return cur.F;
}
int dfs(PLI cur) {
  if (dp.count(cur))
    return dp[cur];
  if (not_enough(cur))
    return dp[cur] = INF;
  if (cur.S == chts)
    return dp[cur] = 0;
  int rtn = INF;
  if (can_put(cur))
    rtn = min(rtn, dfs({process(cur), cur.S + 1}) + 1);
  rtn = min(rtn, dfs({cur.F, cur.S + 1}));
  dp[cur] = rtn;
  return rtn;
}
int main() {
  pw10[0] = 1;
  for (int i = 1; i < N; ++i)
    pw10[i] = pw10[i - 1] * 10;
  while (scanf("%d %d", &h, &w) && (h + w))
    printf("%d\\n", dfs(init()));
}


Error: TLE

Fixed submission:

#pragma GCC optimize "O3"

#define F first
#define S second

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> PII;
typedef pair<int, PII> PIII;

constexpr int N = 15;

int h, w, ans, tmp[N], tot;
char t[N][N + 1];
PIII vs[N];
vector<PII> adj0[N];
vector<int> adj1[N][N];

void init() {
  tot = 0;
  for (int i = 0; i < N; ++i) {
    adj0[i].clear();
    for (int j = 0; j < N; ++j)
      adj1[i][j].clear();
  }
  ans = INT_MAX;
}
void fillup(const string &prm, vector<int> &poss, vector<PII> &adj, char tc) {
  for (size_t i = 0; i < poss.size(); ++i)
    if (prm[i] == '1')
      t[adj[poss[i]].F][adj[poss[i]].S] = tc;
}
bool good(const string &prm, vector<int> &poss, vector<PII> &adj,
          vector<int> &cnts) {
  for (size_t k = 0; k < poss.size(); ++k) {
    if (prm[k] == '1') {
      int i = adj[poss[k]].F, j = adj[poss[k]].S;
      if (t[i][j] != 'x') {
        for (int l : adj1[i][j]) {
          ++cnts[l];
        }
      }
    }
  }
  for (int i = 0; i < tot; ++i)
    if (cnts[i] > vs[i].F)
      return false;
  return true;
}
void dfs(int id, const vector<int> &cnts, int tans) {
  if (tans >= ans)
    return;
  if (id == tot) {
    // cerr << "tans " << tans << endl;
    ans = min(ans, tans);
    return;
  }
  vector<int> poss;
  int num = vs[id].F;
  for (size_t i = 0; i < adj0[id].size(); ++i) {
    if (t[adj0[id][i].F][adj0[id][i].S] == 'x')
      --num;
    else
      poss.push_back(i);
  }
  sort(poss.begin(), poss.end(), [&](const int &p0, const int &p1) {
    return adj1[id][p0].size() < adj1[id][p1].size();
  });
  string prm = string(poss.size() - num, '0') + string(num, '1');
  do {
    vector<int> ncnts = cnts;
    if (good(prm, poss, adj0[id], ncnts)) {
      fillup(prm, poss, adj0[id], 'x');
      dfs(id + 1, ncnts, tans + num);
      fillup(prm, poss, adj0[id], '*');
    }
  } while (next_permutation(prm.begin(), prm.end()));
}
bool in_border(int i, int j) { return i >= 0 && j >= 0 && i < h && j < w; }
void solve() {
  init();
  for (int i = 0; i < h; ++i)
    scanf("%s", t[i]);
  getchar();
  for (int i = 0; i < h; ++i)
    for (int j = 0; j < w; ++j)
      if (isdigit(t[i][j])) {
        for (int i0 = -1; i0 <= 1; ++i0)
          for (int j0 = -1; j0 <= 1; ++j0) {
            int ni = i + i0, nj = j + j0;
            if (in_border(ni, nj) && t[ni][nj] != '.') {
              adj0[tot].emplace_back(ni, nj);
              adj1[ni][nj].push_back(tot);
            }
          }
        vs[tot] = {t[i][j] - '0', {i, j}};
        ++tot;
        t[i][j] = '*';
      }
  // for(int i = 0; i < tot; ++i)
  //   sort(adj0[i].begin(), adj0[i].end(),
  //        [&](const PII &p0, const PII &p1) {
  //          return adj1[p0.F][p0.S].size() < adj1[p1.F][p1.S].size();
  //        });
  vector<int> cnts(tot, 0);
  dfs(0, cnts, 0);
  printf("%d\\n", ans);
}
int main() {
  while (scanf("%d %d", &h, &w) == 2 && (h + w))
    solve();
}