Problem p00739 (C++) — buggy submission, verdict: Runtime Error


#include <algorithm>
#include <climits>
#include <complex>
#include <iostream>
#include <set>
#include <vector>

using namespace std;

typedef unsigned long long u64;
typedef complex<int> point;

int n;
point piece[36];
int pairs[36];
u64 joint[36];

set<u64> wrong;

bool solve(u64 t, u64 w) {
  if (wrong.find(t) != wrong.end())
    return false;

  if ((t | w) == (1ULL << n) - 1)
    return true;

  for (int i = 0; i < n; ++i) {
    u64 tm = 1ULL << i;
    u64 wm = 1ULL << pairs[i];

    if (pairs[i] == -1 || (t & tm) || (w & tm) || (t & wm) || (w & wm) ||
        !(joint[i] & t))
      continue;

    if (solve(t | tm, w | wm))
      return true;
  }

  wrong.insert(t);
  return false;
}

int main() {
  for (int w, h; cin >> w >> h, w | h;) {
    int index[10][10];

    n = 0;

    for (int y = 0; y < h; ++y)
      for (int x = 0; x < w; ++x) {
        int r;
        cin >> r;

        if (r == 1) {
          index[y][x] = n;
          piece[n++] = point(x, y);
        } else {
          index[y][x] = -1;
        }
      }

    for (int i = 0; i < n; ++i) {
      point d(1, 0);
      joint[i] = 0;

      for (int j = 0; j < n; ++j)
        for (int k = 0; k < 4; ++k, d *= point(0, 1))
          if (piece[i] + d == piece[j])
            joint[i] |= 1ULL << j;
    }

    if (n & 1) {
      cout << "NO" << endl;
      continue;
    }

    point base0 = piece[0];

    bool yes = false;

    for (int base_index = 1; base_index < n; ++base_index) {
      point base1 = piece[base_index];

      point rotate = point(1, 0);

      for (int rot = 0; rot < 4; ++rot, rotate *= point(0, 1))
        for (int mirror = 0; mirror <= 1; ++mirror) {
          int rpairs[36];

          fill(rpairs, rpairs + n, -1);
          fill(pairs, pairs + n, -1);

          for (int i = 0; i < n; ++i) {
            point t = piece[i] - base0;
            if (mirror)
              t.imag() = -t.imag();
            t = t * rotate + base1;

            if (t.real() < 0 || w <= t.real() || t.imag() < 0 || h <= t.imag())
              continue;

            pairs[i] = index[t.imag()][t.real()];

            if (pairs[i] != -1)
              rpairs[pairs[i]] = i;
          }

          int i;

          for (i = 0; i < n; ++i)
            if (rpairs[i] == -1 && pairs[i] == -1 || pairs[i] == i)
              break;

          wrong.clear();

          if (i == n && solve(1ULL, 1ULL << base_index)) {
            yes = true;
            goto quit;
          }
        }
    }

  quit:

    cout << (yes ? "YES" : "NO") << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:


#include <algorithm>
#include <iostream>
#include <map>
#include <set>
using namespace std;
typedef set<int> Shape;
#define MAX 12
int W, H, C[MAX][MAX], ncell, sx, sy, tx, ty, sd, td, flip;
bool V[MAX][MAX];
map<Shape, bool> U;

void rotate(int &x, int &y) {
  if (td == 1) {
    swap(x, y);
    x *= (-1);
  } else if (td == 2) {
    x *= (-1);
    y *= (-1);
  } else if (td == 3) {
    swap(x, y);
    y *= (-1);
  }
  x *= flip;
}

bool dfs(Shape shape) {
  if (shape.size() == ncell)
    return true;

  U[shape] = true;

  static const int dx[4] = {0, -1, 0, 1};
  static const int dy[4] = {1, 0, -1, 0};
  int nx, ny, tnx, tny, diffx, diffy;
  Shape nextS;

  for (Shape::iterator it = shape.begin(); it != shape.end(); it++) {
    for (int d = 0; d < 4; d++) {
      nx = (*it) / W + dx[d];
      ny = (*it) % W + dy[d];
      if (!C[nx][ny] || V[nx][ny])
        continue;
      diffx = nx - sx;
      diffy = ny - sy;
      rotate(diffx, diffy);
      tnx = tx + diffx;
      tny = ty + diffy;
      if (nx == tnx && ny == tny)
        continue;
      if (!C[tnx][tny] || V[tnx][tny])
        continue;
      nextS = shape;
      nextS.insert(nx * W + ny);
      if (U[nextS])
        continue;
      V[nx][ny] = V[tnx][tny] = true;
      if (dfs(nextS))
        return true;
      V[nx][ny] = V[tnx][tny] = false;
    }
  }
  return false;
}

bool parse() {
  U = map<Shape, bool>();
  for (int x = 1; x <= H; x++) {
    for (int y = 1; y <= W; y++)
      V[x][y] = 0;
  }
  Shape shape;
  shape.insert(sx * W + sy);
  U[shape] = true;
  V[sx][sy] = V[tx][ty] = true;
  return dfs(shape);
}

bool check() {
  if (ncell % 2 != 0 || ncell < 2)
    return false;
  ncell /= 2;
  for (tx = 1; tx <= H; tx++) {
    for (ty = 1; ty <= W; ty++) {
      if ((tx == sx && ty == sy) || C[tx][ty] == 0)
        continue;
      for (td = 0; td < 4; td++) {
        flip = 1;
        if (parse())
          return true;
        flip = -1;
        if (parse())
          return true;
      }
    }
  }
  return false;
}

int main() {
  while (cin >> W >> H && (W && H)) {
    ncell = 0;
    sx = sy = -1;
    for (int x = 0; x < H + 2; x++) {
      for (int y = 0; y < W + 2; y++) {
        C[x][y] = 0;
        if (1 <= x && 1 <= y && x <= H && y <= W)
          cin >> C[x][y];
        if (C[x][y])
          ncell++;
        if (C[x][y] && sx == -1) {
          sx = x;
          sy = y;
        }
      }
    }
    if (check())
      cout << "YES" << endl;
    else
      cout << "NO" << endl;
  }
  return 0;
}