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

#include <algorithm>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

class Piece {
public:
  int h, w;
  vector<bitset<20>> a;
  int n;

  void read() {
    cin >> h >> w;
    a.assign(h, 0);
    n = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        char c;
        cin >> c;
        if (c == '#') {
          a[i][j] = true;
          ++n;
        }
      }
    }
  }
  bool all() const {
    for (int i = 0; i < h; ++i) {
      if (a[i].count() != w)
        return false;
    }
    return true;
  }
  bool canPut(int y, int x, const Piece &p) const {
    for (int i = 0; i < p.h; ++i) {
      if ((a[y + i] & (p.a[i] << x)).any())
        return false;
    }
    return true;
  }
  void put(int y, int x, const Piece &p) {
    for (int i = 0; i < p.h; ++i)
      a[y + i] |= (p.a[i] << x);
  }
  void remove(int y, int x, const Piece &p) {
    for (int i = 0; i < p.h; ++i)
      a[y + i] &= ~(p.a[i] << x);
  }
  void rotate() {
    vector<bitset<20>> b(w, 0);
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        b[j][i] = a[i][w - 1 - j];
      }
    }
    a.swap(b);
    swap(h, w);
  }
  bool operator<(const Piece &p) const { return n < p.n; }
};

bool solve(Piece &puzzle, const vector<vector<Piece>> &p, int k) {
  if (k == p.size())
    return true;

  Piece prob = puzzle;
  for (unsigned j = k; j < p.size(); ++j) {
    bool ng = true;
    for (int r = 0; r < 4; ++r) {
      for (int y = 0; y <= puzzle.h - p[j][r].h; ++y) {
        for (int x = 0; x <= puzzle.w - p[j][r].w; ++x) {
          if (puzzle.canPut(y, x, p[j][r])) {
            prob.put(y, x, p[j][r]);
            ng = false;
          }
        }
      }
    }

    if (ng)
      return false;
  }
  if (!prob.all())
    return false;

  for (int r = 0; r < 4; ++r) {
    for (int y = 0; y <= puzzle.h - p[k][r].h; ++y) {
      for (int x = 0; x <= puzzle.w - p[k][r].w; ++x) {
        if (puzzle.canPut(y, x, p[k][r])) {
          puzzle.put(y, x, p[k][r]);
          bool ret = solve(puzzle, p, k + 1);
          puzzle.remove(y, x, p[k][r]);
          if (ret)
            return ret;
        }
      }
    }
  }

  return false;
}

int main() {
  for (;;) {
    Piece puzzle;
    puzzle.read();
    if (puzzle.h == 0)
      return 0;

    int n;
    cin >> n;
    vector<vector<Piece>> p(n, vector<Piece>(4));
    for (int i = 0; i < n; ++i) {
      p[i][0].read();
      for (int j = 1; j < 4; ++j) {
        p[i][j] = p[i][j - 1];
        p[i][j].rotate();
      }
    }

    int m;
    cin >> m;
    for (int i = 0; i < m; ++i) {
      int k;
      cin >> k;
      vector<vector<Piece>> p2(k);
      int sum = 0;
      for (int j = 0; j < k; ++j) {
        int x;
        cin >> x;
        p2[j] = p[x - 1];
        sum += p2[j][0].n;
      }

      if (sum != puzzle.h * puzzle.w - puzzle.n) {
        cout << "NO" << endl;
        continue;
      }

      sort(p2.rbegin(), p2.rend());
      if (solve(puzzle, p2, 0))
        cout << "YES" << endl;
      else
        cout << "NO" << endl;
    }
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cfloat>
#include <climits>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

class Piece {
public:
  int h, w;
  vector<bitset<20>> a;
  int n;

  void read() {
    cin >> h >> w;
    a.assign(h, 0);
    n = 0;
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        char c;
        cin >> c;
        if (c == '#') {
          a[i][j] = true;
          ++n;
        }
      }
    }
  }
  void rotate() {
    vector<bitset<20>> b(w, 0);
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        b[j][i] = a[i][w - 1 - j];
      }
    }
    a.swap(b);
    swap(h, w);
  }
  bool operator<(const Piece &p) const { return n < p.n; }
};

bool solve(Piece &puzzle, vector<Piece> &p, int k) {
  if (k == p.size())
    return true;

  for (unsigned j = k; j < p.size(); ++j) {
    bool ng = true;
    for (int r = 0; r < 4; ++r) {
      for (int y = 0; y <= puzzle.h - p[j].h; ++y) {
        for (int x = 0; x <= puzzle.w - p[j].w; ++x) {
          bool canPut = true;
          for (int i = 0; i < p[j].h; ++i) {
            if ((puzzle.a[y + i] & (p[j].a[i] << x)).any()) {
              canPut = false;
              break;
            }
          }

          if (canPut) {
            ng = false;
            break;
          }
        }
        if (!ng)
          break;
      }
      if (!ng)
        break;
      p[j].rotate();
    }

    if (ng)
      return false;
  }

  for (int r = 0; r < 4; ++r) {
    for (int y = 0; y <= puzzle.h - p[k].h; ++y) {
      for (int x = 0; x <= puzzle.w - p[k].w; ++x) {
        bool canPut = true;
        for (int i = 0; i < p[k].h; ++i) {
          if ((puzzle.a[y + i] & (p[k].a[i] << x)).any()) {
            canPut = false;
            break;
          }
        }

        if (canPut) {
          for (int i = 0; i < p[k].h; ++i)
            puzzle.a[y + i] |= (p[k].a[i] << x);
          bool ret = solve(puzzle, p, k + 1);
          for (int i = 0; i < p[k].h; ++i)
            puzzle.a[y + i] &= ~(p[k].a[i] << x);
          if (ret)
            return ret;
        }
      }
    }
    p[k].rotate();
  }

  return false;
}

int main() {
  for (;;) {
    Piece puzzle;
    puzzle.read();
    if (puzzle.h == 0)
      return 0;

    int n;
    cin >> n;
    vector<Piece> p(n);
    for (int i = 0; i < n; ++i)
      p[i].read();

    int m;
    cin >> m;
    for (int i = 0; i < m; ++i) {
      int k;
      cin >> k;
      vector<Piece> p2(k);
      int sum = 0;
      for (int j = 0; j < k; ++j) {
        int x;
        cin >> x;
        p2[j] = p[x - 1];
        sum += p2[j].n;
      }

      if (sum != puzzle.h * puzzle.w - puzzle.n) {
        cout << "NO" << endl;
        continue;
      }

      sort(p2.rbegin(), p2.rend());
      if (solve(puzzle, p2, 0))
        cout << "YES" << endl;
      else
        cout << "NO" << endl;
    }
  }
}