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

#include <bits/stdc++.h>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define IINF (INT_MAX)
#define MAX 9

using namespace std;

typedef unsigned long long ull;

const string Y = "YES", N = "NO";
int n, field[MAX][MAX], V;
vector<int> V_sum;
vector<int> coor;

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

inline bool isValid(int x, int y) { return 0 <= x && x < n && 0 <= y && y < n; }

bool check(ull used, int cur, int x, int y) {
  int sp_x = x, sp_y = y;

  REP(i, cur, V) {
    ull tmp_used = used;
    if (i != cur)
      sp_x = coor[i] % n, sp_y = coor[i] / n;
    deque<int> deq;
    deq.push_back(sp_x + sp_y * n);
    bool ok = false;
    int score = V_sum[i];
    if (score == 0)
      ok = true;
    while (!deq.empty()) {
      int p = deq.front();
      deq.pop_front();
      int cx = p % n, cy = p / n;
      if (ok)
        break;
      rep(j, 4) {
        int nx = cx + dx[j];
        int ny = cy + dy[j];
        if (!isValid(nx, ny))
          continue;
        if ((tmp_used >> (nx + ny * n)) & 1)
          continue;
        tmp_used |= (1ULL << (nx + ny * n));
        score += field[ny][nx];
        if (score >= 0) {
          ok = true;
          break;
        }
        deq.push_back(nx + ny * n);
      }
    }
    if (!ok)
      return false;
  }
  return true;
}

bool dfs(ull used, int cur, int pre, int x, int y, int sum) {

  if (cur >= V) {
    // if( used == (1ULL<<(n*n))-1ULL ) return true;
    // return false;
    return true;
  }

  // if(!check(used,cur,x,y))return false;

  rep(i, 4) {
    // if( i == pre ) continue;
    int nx = x + dx[i];
    int ny = y + dy[i];
    if (!isValid(nx, ny))
      continue;
    if ((used >> (nx + ny * n)) & 1)
      continue;
    if (field[ny][nx] < 0)
      continue;
    if (sum + field[ny][nx] > V_sum[cur])
      continue;

    int ncur = cur;
    int npre = (i + 2) % 4;
    int nsum = sum + field[ny][nx];
    ull nused = used | (1ULL << (nx + ny * n));
    if (sum + field[ny][nx] == V_sum[cur]) {
      ncur++;
      npre = -1;
      nsum = 0;
      nx = coor[ncur] % n;
      ny = coor[ncur] / n;
    }
    if (dfs(nused, ncur, npre, nx, ny, nsum))
      return true;
  }

  return false;
}

int main() {

  while (scanf("%d", &n), n) {
    ull initial_state = 0ULL;
    V = 0;
    coor.clear();
    V_sum.clear();
    int sum = 0;
    rep(i, n) rep(j, n) {
      scanf("%d", &field[i][j]);
      sum += field[i][j];
      if (field[i][j] < 0) {
        V++;
        ull tmp = (1ULL << (j + i * n));
        coor.push_back(j + i * n);
        initial_state |= (1ULL << (j + i * n));
        V_sum.push_back(-field[i][j]);
      }
    }

    if (sum != 0) {
      cout << N << endl;
      continue;
    }

    bool res = dfs(initial_state, 0, -1, coor[0] % n, coor[0] / n, 0);
    cout << (res ? Y : N) << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define IINF (INT_MAX)
#define MAX 9

using namespace std;

typedef unsigned long long ull;

const string Y = "YES", N = "NO";
int n, field[MAX][MAX], V;
vector<ull> cache;
vector<int> V_sum;
vector<int> coor;
set<vector<ull>> visited;

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

inline bool isValid(int x, int y) { return 0 <= x && x < n && 0 <= y && y < n; }

bool check(ull used, int cur, int x, int y) {
  int sp_x = x, sp_y = y;

  REP(i, cur, V) {
    ull tmp_used = used;
    if (i != cur)
      sp_x = coor[i] % n, sp_y = coor[i] / n;
    deque<int> deq;
    deq.push_back(sp_x + sp_y * n);
    bool ok = false;
    int score = V_sum[i];
    if (score == 0)
      ok = true;
    while (!deq.empty()) {
      int p = deq.front();
      deq.pop_front();
      int cx = p % n, cy = p / n;
      if (ok)
        break;
      rep(j, 4) {
        int nx = cx + dx[j];
        int ny = cy + dy[j];
        if (!isValid(nx, ny))
          continue;
        if ((tmp_used >> (nx + ny * n)) & 1)
          continue;
        tmp_used |= (1ULL << (nx + ny * n));
        score += field[ny][nx];
        if (score >= 0) {
          ok = true;
          break;
        }
        deq.push_back(nx + ny * n);
      }
    }
    if (!ok)
      return false;
  }
  return true;
}

bool dfs(ull used, int cur, int pre, int x, int y) {

  if (cur >= V) {
    if (used == (1ULL << (n * n)) - 1ULL) {
      rep(i, V) if (V_sum[i] != 0) return false;
      return true;
    }
    return false;
  }

  if (!check(used, cur, x, y))
    return false;

  rep(i, 4) {
    if (i == pre)
      continue;
    int nx = x + dx[i];
    int ny = y + dy[i];
    if (!isValid(nx, ny))
      continue;
    if ((used >> (nx + ny * n)) & 1)
      continue;

    int cost = field[ny][nx];
    if (cost + V_sum[cur] > 0)
      continue;

    int next = cur;
    int npre = (i + 2) % 4;
    ull next_used = used | (1ULL << (nx + ny * n));

    if (cost + V_sum[cur] == 0) {
      next++;
      npre = -1;
      nx = coor[next] % n;
      ny = coor[next] / n;
    }
    V_sum[cur] += cost;
    if (dfs(next_used, next, npre, nx, ny))
      return true;
    V_sum[cur] -= cost;
  }
  return false;
}

int main() {

  while (scanf("%d", &n), n) {
    visited.clear();
    ull initial_state = 0ULL;
    V = 0;
    cache.clear();
    coor.clear();
    V_sum.clear();
    int sum = 0;
    rep(i, n) rep(j, n) {
      scanf("%d", &field[i][j]);
      sum += field[i][j];
      if (field[i][j] < 0) {
        V++;
        ull tmp = (1ULL << (j + i * n));
        cache.push_back(tmp);
        coor.push_back(j + i * n);
        initial_state |= (1ULL << (j + i * n));
        V_sum.push_back(field[i][j]);
      }
    }

    if (sum != 0) {
      cout << N << endl;
      continue;
    }

    bool res = dfs(initial_state, 0, -1, coor[0] % n, coor[0] / n);
    cout << (res ? Y : N) << endl;
  }

  return 0;
}