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

#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
using namespace std;

enum { Blank, Fill };

class Piece {
  vector<vector<int>> tile_value[4];
  int h_value[4], w_value[4];
  int dx_value[4];
  int direction;

public:
  Piece(vector<vector<int>> tile) {
    direction = 0;
    for (int d = 0; d < 4; ++d) {
      h_value[d] = d & 1 ? tile[0].size() : tile.size();
      w_value[d] = d & 1 ? tile.size() : tile[0].size();
    }
    for (int d = 0; d < 4; ++d)
      tile_value[d].resize(h_value[d]);
    for (int d = 0; d < 4; ++d)
      for (int i = 0; i < h_value[d]; ++i)
        tile_value[d][i].resize(w_value[d]);
    tile_value[0] = tile;
    for (int d = 1; d < 4; ++d)
      for (int i = 0; i < h_value[d]; ++i)
        for (int j = 0; j < w_value[d]; ++j)
          tile_value[d][i][j] = tile_value[d - 1][j][h_value[d] - 1 - i];
    for (int d = 0; d < 4; ++d)
      for (int j = 0; j < w_value[d]; ++j) {
        if (tile_value[d][0][j] == Blank)
          continue;
        dx_value[d] = j;
        break;
      }
  }
  int h() { return h_value[direction]; }
  int w() { return w_value[direction]; }
  int tile(int i, int j) { return tile_value[direction][i][j]; }
  int dx() { return dx_value[direction]; }
  void rotate() { direction = (direction + 1) % 4; }
};

int h, w;
vector<Piece> piece;
map<pair<vector<vector<int>>, vector<int>>, bool> memo;

bool dfs(vector<vector<int>> puzzle, vector<int> candidate) {
  if (memo.count(make_pair(puzzle, candidate)))
    return memo[make_pair(puzzle, candidate)];
  bool ok = true;
  int y, x;
  for (int i = 0; ok && i < h; ++i)
    for (int j = 0; ok && j < w; ++j) {
      if (puzzle[i][j] == Fill)
        continue;
      y = i;
      x = j;
      ok = false;
    }
  if (ok)
    return memo[make_pair(puzzle, candidate)] = (candidate.size() == 0);

  for (int c = 0; c < candidate.size(); ++c) {
    Piece p = piece[candidate[c]];
    for (int d = 0; d < 4; ++d) {
      p.rotate();
      if (h < y + p.h())
        continue;
      if (w < x - p.dx() + p.w())
        continue;
      if (x - p.dx() < 0)
        continue;
      vector<vector<int>> _puzzle = puzzle;
      ok = true;
      for (int i = 0; ok && i < p.h(); ++i)
        for (int j = 0; ok && j < p.w(); ++j) {
          _puzzle[y + i][x - p.dx() + j] += p.tile(i, j);
          if (_puzzle[y + i][x - p.dx() + j] == 2)
            ok = false;
        }
      if (!ok)
        continue;
      vector<int> _candidate = candidate;
      _candidate.erase(_candidate.begin() + c);
      if (dfs(_puzzle, _candidate))
        return memo[make_pair(puzzle, candidate)] = true;
    }
  }
  return memo[make_pair(puzzle, candidate)] = false;
}

int main() {
  while (cin >> h >> w, h | w) {
    vector<vector<int>> puzzle(h, vector<int>(w));
    for (int i = 0; i < h; ++i) {
      string input;
      cin >> input;
      for (int j = 0; j < w; ++j)
        puzzle[i][j] = (input[j] == '#' ? Fill : Blank);
    }

    int n;
    piece.clear();
    for (cin >> n; 0 < n; --n) {
      int h1, w1;
      cin >> h1 >> w1;
      vector<vector<int>> tile(h1, vector<int>(w1));
      for (int i = 0; i < h1; ++i) {
        string input;
        cin >> input;
        for (int j = 0; j < w1; ++j)
          tile[i][j] = (input[j] == '#' ? Fill : Blank);
      }
      piece.push_back(Piece(tile));
    }

    int p;
    for (cin >> p; 0 < p; --p) {
      int k;
      vector<int> candidate;
      for (cin >> k; 0 < k; --k) {
        int x;
        cin >> x;
        candidate.push_back(x - 1);
      }
      memo.clear();
      sort(candidate.begin(), candidate.end());
      cout << (dfs(puzzle, candidate) ? "YES" : "NO") << endl;
    }
  }
}

Error: TLE

Fixed submission:


#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

enum { Blank, Fill };

class Piece {
  vector<vector<int>> tile_value[4];
  int h_value[4], w_value[4];
  int dx_value[4];
  int direction;

public:
  Piece(vector<vector<int>> tile) {
    direction = 0;
    for (int d = 0; d < 4; ++d) {
      h_value[d] = d & 1 ? tile[0].size() : tile.size();
      w_value[d] = d & 1 ? tile.size() : tile[0].size();
    }
    for (int d = 0; d < 4; ++d)
      tile_value[d].resize(h_value[d]);
    for (int d = 0; d < 4; ++d)
      for (int i = 0; i < h_value[d]; ++i)
        tile_value[d][i].resize(w_value[d]);
    tile_value[0] = tile;
    for (int d = 1; d < 4; ++d)
      for (int i = 0; i < h_value[d]; ++i)
        for (int j = 0; j < w_value[d]; ++j)
          tile_value[d][i][j] = tile_value[d - 1][j][h_value[d] - 1 - i];
    for (int d = 0; d < 4; ++d)
      for (int j = 0; j < w_value[d]; ++j) {
        if (tile_value[d][0][j] == Blank)
          continue;
        dx_value[d] = j;
        break;
      }
  }
  int h() { return h_value[direction]; }
  int w() { return w_value[direction]; }
  int tile(int i, int j) { return tile_value[direction][i][j]; }
  int dx() { return dx_value[direction]; }
  void rotate() { direction = (direction + 1) % 4; }
};

int h, w;
vector<Piece> piece;

bool dfs(vector<vector<int>> puzzle, vector<int> candidate) {
  bool ok = true;
  int y, x;
  for (int i = 0; ok && i < h; ++i)
    for (int j = 0; ok && j < w; ++j) {
      if (puzzle[i][j] == Fill)
        continue;
      y = i;
      x = j;
      ok = false;
    }
  if (ok)
    return candidate.size() == 0;

  for (int c = 0; c < candidate.size(); ++c) {
    Piece p = piece[candidate[c]];
    for (int d = 0; d < 4; ++d) {
      p.rotate();
      if (h < y + p.h())
        continue;
      if (w < x - p.dx() + p.w())
        continue;
      if (x - p.dx() < 0)
        continue;
      vector<vector<int>> _puzzle = puzzle;
      ok = true;
      for (int i = 0; ok && i < p.h(); ++i)
        for (int j = 0; ok && j < p.w(); ++j) {
          _puzzle[y + i][x - p.dx() + j] += p.tile(i, j);
          if (_puzzle[y + i][x - p.dx() + j] == 2)
            ok = false;
        }
      if (!ok)
        continue;
      vector<int> _candidate = candidate;
      _candidate.erase(_candidate.begin() + c);
      if (dfs(_puzzle, _candidate))
        return true;
    }
  }
  return false;
}

int main() {
  while (cin >> h >> w, h | w) {
    vector<vector<int>> puzzle(h, vector<int>(w));
    for (int i = 0; i < h; ++i) {
      string input;
      cin >> input;
      for (int j = 0; j < w; ++j)
        puzzle[i][j] = (input[j] == '#' ? Fill : Blank);
    }

    int n;
    piece.clear();
    for (cin >> n; 0 < n; --n) {
      int h1, w1;
      cin >> h1 >> w1;
      vector<vector<int>> tile(h1, vector<int>(w1));
      for (int i = 0; i < h1; ++i) {
        string input;
        cin >> input;
        for (int j = 0; j < w1; ++j)
          tile[i][j] = (input[j] == '#' ? Fill : Blank);
      }
      piece.push_back(Piece(tile));
    }

    int p;
    for (cin >> p; 0 < p; --p) {
      int k;
      vector<int> candidate;
      for (cin >> k; 0 < k; --k) {
        int x;
        cin >> x;
        candidate.push_back(x - 1);
      }
      sort(candidate.begin(), candidate.end());
      cout << (dfs(puzzle, candidate) ? "YES" : "NO") << endl;
    }
  }
}