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

#include <algorithm>
#include <bitset>
#include <functional>
#include <iostream>
#include <string>
#include <vector>

#define NIL (-1)
#define MAX 22
#define MAX_PIECES 10
#define BURIED 1
#define NONE 0
#define PZL 1
using namespace std;

class CPiece {
public:
  class piece {
  public:
    int si, sj;
    int H, W;
    short m[MAX][MAX];
    piece() {
      for (int i = 0; i < MAX; ++i)
        for (int j = 0; j < MAX; ++j)
          m[i][j] = NONE;
    }
    void Print() const {
      for (int i = 1; i <= H; ++i) {
        for (int j = 1; j <= W; ++j)
          cout << (m[i][j] == PZL ? '#' : '.');
        cout << '\\n';
      }
    }
    void DetermineSiSj() {
      for (int i = 1; i <= H; ++i)
        for (int j = 1; j <= W; ++j)
          if (m[i][j] == PZL) {
            si = i - 1;
            sj = j - 1;
            return;
          }
    }
    bool operator==(const CPiece::piece &t) const {
      if (H == t.H && W == t.W) {
        for (int i = 1; i <= H; ++i)
          for (int j = 1; j <= W; ++j)
            if (m[i][j] != t.m[i][j])
              return false;
        return true;
      } else
        return false;
    }
  };
  vector<piece> rots;
  void Minimize() {
    int offX = 0, offY = 0;
    for (int i = 1; i <= rots[0].H; ++i) {
      bool bClearThisLine = true;
      for (int j = 1; j <= rots[0].W; ++j) {
        if (rots[0].m[i][j] == PZL)
          bClearThisLine = false;
      }
      if (!bClearThisLine)
        break;
      else
        offY++;
    }
    for (int i = 1; i <= rots[0].W; ++i) {
      bool bClearThisLine = true;
      for (int j = 1; j <= rots[0].H; ++j) {
        if (rots[0].m[j][i] == PZL)
          bClearThisLine = false;
      }
      if (!bClearThisLine)
        break;
      else
        offX++;
    }

    for (int i = 1; i <= rots[0].H; ++i) {
      for (int j = 1; j <= rots[0].W; ++j) {
        this->rots[0].m[i][j] = this->rots[0].m[i + offY][j + offX];
      }
    }
    rots[0].H -= offY;
    rots[0].W -= offX;

    offY = 0;
    offX = 0;

    for (int i = rots[0].H; i >= 1; --i) {
      bool bClearThisLine = true;
      for (int j = rots[0].W; j >= 1; --j) {
        if (rots[0].m[i][j] == PZL)
          bClearThisLine = false;
      }
      if (!bClearThisLine)
        break;
      else
        offY++;
    }
    for (int i = rots[0].W; i >= 1; --i) {
      bool bClearThisLine = true;
      for (int j = rots[0].H; j >= 1; --j) {
        if (rots[0].m[j][i] == PZL)
          bClearThisLine = false;
      }
      if (!bClearThisLine)
        break;
      else
        offX++;
    }
    this->rots[0].H -= offY;
    this->rots[0].W -= offX;
  }
  void CreateRotations() {
    rots[0].DetermineSiSj();
    for (int i = 1; i <= 3; ++i) {
      bool bExist = false;
      piece next;

      TurnRight90(rots[rots.size() - 1], next);
      next.H = rots[rots.size() - 1].W;
      next.W = rots[rots.size() - 1].H;
      next.DetermineSiSj();

      if (rots.end() == find(rots.begin(), rots.end(), next))
        rots.push_back(next);
    }
    // cout << rots.size() << endl;
  }
  int CountPuzzleCells() const {
    int ret = 0;
    for (int i = 1; i <= rots[0].H; ++i)
      for (int j = 1; j <= rots[0].W; ++j)
        if (rots[0].m[i][j] == PZL)
          ++ret;
    return ret;
  }
  bool operator>(const CPiece &t) const {
    int area = this->rots[0].H * this->rots[0].W;
    int area_t = t.rots[0].H * t.rots[0].W;
    if (area == area_t)
      return this->CountPuzzleCells() > t.CountPuzzleCells();
    else
      return area > area_t;
  }

private:
  void TurnRight90(piece &from, piece &t) {
    double offsetX = (from.W + 1) / 2.0;
    double offsetY = (from.H + 1) / 2.0;

    for (double i = 1 - offsetY; i <= from.H - offsetY + 0.1; i += 1.0) {
      for (double j = 1 - offsetX; j <= from.W - offsetX + 0.1; j += 1.0) {
        double ti = j;
        double tj = -i;
        t.m[int(ti + offsetX)][int(tj + offsetY)] =
            from.m[int(i + offsetY)][int(j + offsetX)];
      }
    }
  }
};

class CPieces {
public:
  vector<CPiece> vPieces;
  bitset<MAX_PIECES> bUse;
  bitset<MAX_PIECES> bUsed;
};

class CPuzzle {
public:
  int H, W;
  short m[MAX][MAX];
  short chk[MAX][MAX];

  bool inRangeHeight(int i) { return 1 <= i && i <= H; }
  bool inRangeWidth(int j) { return 1 <= j && j <= W; }
  void Initialize() {
    for (int i = 0; i < MAX; ++i)
      for (int j = 0; j < MAX; ++j) {
        m[i][j] = BURIED;
        chk[MAX][MAX] = 0;
      }
  }
  void Print() {
    for (int i = 1; i <= H; ++i) {
      for (int j = 1; j <= W; ++j)
        cout << (m[i][j] == BURIED ? '#' : '.');
      cout << '\\n';
    }
  }
  bool CheckAndPutPiece(int i, int j, unsigned int choose, int rot,
                        CPieces &ps) {
    int tmpm[MAX][MAX];
    bool bOk = true;
    CPiece::piece &pce = ps.vPieces[choose].rots[rot];

    for (int ci = 0; ci < MAX; ++ci)
      for (int cj = 0; cj < MAX; ++cj)
        tmpm[ci][cj] = m[ci][cj];

    PutPiece(i, j, pce);

    for (int ci = 1; ci <= H; ++ci) {
      for (int cj = 1; cj <= W; ++cj) {
        if (m[ci][cj] == NONE) {
          bool bFound = false;
          for (unsigned int k = 0; k < ps.vPieces.size() && !bFound; ++k) {
            if (k != choose && ps.bUse[k] && !ps.bUsed[k]) {
              for (unsigned int l = 0; l < ps.vPieces[k].rots.size() && !bFound;
                   ++l) {
                if (TryPutPiece(ci - ps.vPieces[k].rots[l].si,
                                cj - ps.vPieces[k].rots[l].sj,
                                ps.vPieces[k].rots[l])) {
                  CheckPiece(ci - ps.vPieces[k].rots[l].si,
                             cj - ps.vPieces[k].rots[l].sj,
                             ps.vPieces[k].rots[l]);
                }
              }
            }
          }
        }
      }
    }

    for (int ci = 1; ci <= H && bOk; ++ci)
      for (int cj = 1; cj <= W && bOk; ++cj)
        if (m[ci][cj] == NONE && chk[ci][cj] == 0)
          bOk = false;

    if (!bOk) {
      for (int ci = 0; ci < MAX; ++ci)
        for (int cj = 0; cj < MAX; ++cj)
          m[ci][cj] = tmpm[ci][cj];
      return false;
    } else
      return true;
  }
  void ResetChk() {
    for (int i = 0; i < MAX; ++i)
      for (int j = 0; j < MAX; ++j)
        chk[i][j] = 0;
  }
  bool TryPutPiece(int i, int j, CPiece::piece &p) {
    CPiece::piece &pce = p;

    if (!inRangeHeight(i) || !inRangeWidth(j) ||
        !inRangeHeight(i + pce.H - 1) || !inRangeWidth(j + pce.W - 1))
      return false;

    for (int ci = i; ci <= i + pce.H - 1; ++ci)
      for (int cj = j; cj <= j + pce.W - 1; ++cj)
        if (m[ci][cj] == BURIED && pce.m[ci - i + 1][cj - j + 1] == PZL)
          return false;
    return true;
  }

  bool Complete() {
    for (int i = 1; i <= H; ++i)
      for (int j = 1; j <= W; ++j)
        if (m[i][j] == NONE)
          return false;
    return true;
  }
  int CountEmptyCells() {
    int ret = 0;
    for (int i = 1; i <= H; ++i)
      for (int j = 1; j <= W; ++j)
        if (m[i][j] == NONE)
          ++ret;
    return ret;
  }

private:
  void CheckPiece(int i, int j, CPiece::piece &p) {
    CPiece::piece &pce = p;

    if (!inRangeHeight(i) || !inRangeWidth(j) ||
        !inRangeHeight(i + pce.H - 1) || !inRangeWidth(j + pce.W - 1))
      return;

    for (int ci = i; ci <= i + pce.H - 1; ++ci)
      for (int cj = j; cj <= j + pce.W - 1; ++cj)
        if (m[ci][cj] == NONE && pce.m[ci - i + 1][cj - j + 1] == PZL)
          chk[ci][cj] = 1;
  }
  void PutPiece(int i, int j, CPiece::piece &p) {
    CPiece::piece &pce = p;

    for (int ci = i; ci <= i + pce.H - 1; ++ci)
      for (int cj = j; cj <= j + pce.W - 1; ++cj)
        if (m[ci][cj] == NONE && pce.m[ci - i + 1][cj - j + 1] == PZL)
          m[ci][cj] = BURIED;
  }
};

bool DFS(CPuzzle &p, CPieces &ps, bool &bAbort) {
  int choose = NIL;

  // p.Print();cout<<endl;

  for (unsigned int i = 0; i < ps.vPieces.size(); ++i) {
    if (ps.bUse[i] && !ps.bUsed[i]) {
      choose = i;
      break;
    }
  }

  if (choose == NIL) {
    if (p.Complete())
      return true;
    else
      return false;
  } else if (p.Complete()) {
    bAbort = true;
    return true;
  }

  for (unsigned int k = 0; k < ps.vPieces[choose].rots.size(); ++k) {

    /*cout << "Considering : "<<ps.vPieces[choose].rots[k].si <<","
    <<ps.vPieces[choose].rots[k].sj<<endl; ps.vPieces[choose].rots[k].Print();
    cout << endl;*/

    for (int i = 1; i <= p.H; ++i) {
      for (int j = 1; j <= p.W; ++j) {
        if (p.m[i][j] == NONE) {
          if (p.TryPutPiece(i - ps.vPieces[choose].rots[k].si,
                            j - ps.vPieces[choose].rots[k].sj,
                            ps.vPieces[choose].rots[k])) {
            CPuzzle pzl_tmp = p;
            bool bResult;

            /*cout << "Chosen: " << choose << " (i,j) = (" << i << "," << j <<
            ")\\n"; cout << "Piece :\\n"; ps.vPieces[choose].rots[k].Print(); cout
            << endl;*/

            pzl_tmp.ResetChk();
            if (pzl_tmp.CheckAndPutPiece(i - ps.vPieces[choose].rots[k].si,
                                         j - ps.vPieces[choose].rots[k].sj,
                                         choose, k, ps)) {
              ps.bUsed.set(choose);
              bResult = DFS(pzl_tmp, ps, bAbort);
              if (bResult)
                return true;
              ps.bUsed.reset(choose);
            }
          }
        }
      }
    }
  }
  return false;
}
int main() {
  while (true) {
    int n;
    int p, pnum;
    CPuzzle pzl;
    CPieces ps;

    pzl.Initialize();

    cin >> pzl.H >> pzl.W;

    if (pzl.H == 0 && pzl.W == 0)
      break;

    for (int i = 1; i <= pzl.H; ++i) {
      string s;
      cin >> s;
      for (int j = 1; j <= pzl.W; ++j) {
        if (s[j - 1] == '#')
          pzl.m[i][j] = BURIED;
        else
          pzl.m[i][j] = NONE;
      }
    }

    cin >> n;
    for (int i = 0; i < n; ++i) {
      CPiece tmp;
      CPiece::piece t;

      cin >> t.H >> t.W;
      for (int j = 1; j <= t.H; ++j) {
        string s;
        cin >> s;
        for (int k = 1; k <= t.W; ++k) {
          if (s[k - 1] == '#')
            t.m[j][k] = PZL;
          else
            t.m[j][k] = NONE;
        }
      }
      tmp.rots.push_back(t);
      tmp.Minimize();
      tmp.CreateRotations();
      ps.vPieces.push_back(tmp);
    }

    cin >> p;
    for (int i = 0; i < p; ++i) {
      cin >> pnum;
      bool bAbort = false;
      int cntPzl = 0;
      int cntPss = 0;
      CPuzzle pzl_tmp = pzl;
      CPieces ps_tmp;

      ps_tmp.bUse.reset();
      ps_tmp.bUsed.reset();
      for (int j = 0; j < pnum; ++j) {
        int t;
        cin >> t;
        ps_tmp.vPieces.push_back(ps.vPieces[t - 1]);
        cntPss += ps.vPieces[t - 1].CountPuzzleCells();
        ps_tmp.bUse.set(j);
      }
      cntPzl = pzl_tmp.CountEmptyCells();

      if (cntPzl != cntPss) {
        cout << "NO\\n";
        continue;
      }

      /* ツパツズツδ仰づ個妥・ツつォツつ「ツ渉づ可青ョツ療ア */
      sort(ps_tmp.vPieces.begin(), ps_tmp.vPieces.end(), greater<CPiece>());

      if (DFS(pzl_tmp, ps_tmp, bAbort))
        cout << (bAbort ? "NO\\n" : "YES\\n");
      else
        cout << "NO\\n";
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <functional>
#include <iostream>
#include <string>
#include <vector>

#define NIL (-1)
#define MAX 22
#define MAX_PIECES 10
#define BURIED 1
#define NONE 0
#define PZL 1
using namespace std;

class CPiece {
public:
  class piece {
  public:
    int si, sj;
    int H, W;
    short m[MAX][MAX];
    piece() {
      for (int i = 0; i < MAX; ++i) {
        for (int j = 0; j < MAX; ++j) {
          m[i][j] = NONE;
        }
      }
    }
    void Print() {
      for (int i = 1; i <= H; ++i) {
        for (int j = 1; j <= W; ++j) {
          cout << (m[i][j] == PZL ? '#' : '.');
        }
        cout << '\\n';
      }
    }
    void DetermineSiSj() {
      for (int i = 1; i <= H; ++i)
        for (int j = 1; j <= W; ++j)
          if (m[i][j] == PZL) {
            si = i - 1;
            sj = j - 1;
            return;
          }
    }
  };
  int rot;
  piece pr[4];
  void Minimize() {
    int offX = 0, offY = 0;
    for (int i = 1; i <= pr[0].H; ++i) {
      bool bClearThisLine = true;
      for (int j = 1; j <= pr[0].W; ++j) {
        if (pr[0].m[i][j] == PZL)
          bClearThisLine = false;
      }
      if (!bClearThisLine)
        break;
      else
        offY++;
    }
    for (int i = 1; i <= pr[0].W; ++i) {
      bool bClearThisLine = true;
      for (int j = 1; j <= pr[0].H; ++j) {
        if (pr[0].m[j][i] == PZL)
          bClearThisLine = false;
      }
      if (!bClearThisLine)
        break;
      else
        offX++;
    }

    for (int i = 1; i <= pr[0].H; ++i) {
      for (int j = 1; j <= pr[0].W; ++j) {
        this->pr[0].m[i][j] = this->pr[0].m[i + offY][j + offX];
      }
    }
    pr[0].H -= offY;
    pr[0].W -= offX;

    offY = 0;
    offX = 0;

    for (int i = pr[0].H; i >= 1; --i) {
      bool bClearThisLine = true;
      for (int j = pr[0].W; j >= 1; --j) {
        if (pr[0].m[i][j] == PZL)
          bClearThisLine = false;
      }
      if (!bClearThisLine)
        break;
      else
        offY++;
    }
    for (int i = pr[0].W; i >= 1; --i) {
      bool bClearThisLine = true;
      for (int j = pr[0].H; j >= 1; --j) {
        if (pr[0].m[j][i] == PZL)
          bClearThisLine = false;
      }
      if (!bClearThisLine)
        break;
      else
        offX++;
    }
    this->pr[0].H -= offY;
    this->pr[0].W -= offX;
  }
  void CreateRotations() {
    pr[0].DetermineSiSj();

    // 90ツ度
    TurnRight90(pr[0], pr[1]);
    pr[1].H = pr[0].W;
    pr[1].W = pr[0].H;
    pr[1].DetermineSiSj();

    // 180ツ度
    TurnRight90(pr[1], pr[2]);
    pr[2].H = pr[0].H;
    pr[2].W = pr[0].W;
    pr[2].DetermineSiSj();

    // 270ツ度
    TurnRight90(pr[2], pr[3]);
    pr[3].H = pr[0].W;
    pr[3].W = pr[0].H;
    pr[3].DetermineSiSj();
  }
  int CountPuzzleCells() const {
    int ret = 0;
    for (int i = 1; i <= pr[0].H; ++i) {
      for (int j = 1; j <= pr[0].W; ++j) {
        if (pr[0].m[i][j] == PZL)
          ++ret;
      }
    }
    return ret;
  }
  bool operator>(const CPiece &t) const {
    int area = this->pr[0].H * this->pr[0].W;
    int area_t = t.pr[0].H * t.pr[0].W;
    if (area == area_t)
      return this->CountPuzzleCells() > t.CountPuzzleCells();
    else
      return area > area_t;
  }

private:
  void TurnRight90(piece &from, piece &t) {
    double offsetX = (from.W + 1) / 2.0;
    double offsetY = (from.H + 1) / 2.0;

    for (double i = 1 - offsetY; i <= from.H - offsetY + 0.1; i += 1.0) {
      for (double j = 1 - offsetX; j <= from.W - offsetX + 0.1; j += 1.0) {
        double ti = j;
        double tj = -i;
        t.m[int(ti + offsetX)][int(tj + offsetY)] =
            from.m[int(i + offsetY)][int(j + offsetX)];
      }
    }
  }
};

class CPieces {
public:
  vector<CPiece> vPieces;
  bitset<MAX_PIECES> bUse;
  bitset<MAX_PIECES> bUsed;
};

class CPuzzle {
public:
  int H, W;
  short m[MAX][MAX];
  short chk[MAX][MAX];

  bool inRangeHeight(int i) { return 1 <= i && i <= H; }
  bool inRangeWidth(int j) { return 1 <= j && j <= W; }
  void Initialize() {
    for (int i = 0; i < MAX; ++i) {
      for (int j = 0; j < MAX; ++j) {
        m[i][j] = BURIED;
        chk[MAX][MAX] = 0;
      }
    }
  }
  void Print() {
    for (int i = 1; i <= H; ++i) {
      for (int j = 1; j <= W; ++j) {
        cout << (m[i][j] == BURIED ? '#' : '.');
      }
      cout << '\\n';
    }
  }
  bool CheckAndPutPiece(int i, int j, int choose, int rot, CPieces &ps) {
    int tmpm[MAX][MAX];
    bool bOk = true;
    CPiece::piece &pce = ps.vPieces[choose].pr[rot];

    for (int ci = 0; ci < MAX; ++ci)
      for (int cj = 0; cj < MAX; ++cj)
        tmpm[ci][cj] = m[ci][cj];

    PutPiece(i, j, pce);

    for (int ci = 1; ci <= H; ++ci) {
      for (int cj = 1; cj <= W; ++cj) {
        if (m[ci][cj] == NONE) {
          bool bFound = false;
          for (unsigned int k = 0; k < ps.vPieces.size() && !bFound; ++k) {
            if (k != choose && ps.bUse[k] && !ps.bUsed[k]) {
              for (int l = 0; l < 4 && !bFound; ++l) {
                if (TryPutPiece(ci - ps.vPieces[k].pr[l].si,
                                cj - ps.vPieces[k].pr[l].sj,
                                ps.vPieces[k].pr[l])) {
                  CheckPiece(ci - ps.vPieces[k].pr[l].si,
                             cj - ps.vPieces[k].pr[l].sj, ps.vPieces[k].pr[l]);
                }
              }
            }
          }
        }
      }
    }
    for (int ci = 1; ci <= H && bOk; ++ci) {
      for (int cj = 1; cj <= W && bOk; ++cj) {
        if (m[ci][cj] == NONE && chk[ci][cj] == 0) {
          bOk = false;
        }
      }
    }
    if (!bOk) {
      for (int ci = 0; ci < MAX; ++ci)
        for (int cj = 0; cj < MAX; ++cj)
          m[ci][cj] = tmpm[ci][cj];
      return false;
    } else
      return true;
  }
  void ResetChk() {
    for (int i = 0; i < MAX; ++i)
      for (int j = 0; j < MAX; ++j)
        chk[i][j] = 0;
  }
  bool TryPutPiece(int i, int j, CPiece::piece &p) {
    CPiece::piece &pce = p;

    // if( i+pce.H >= this->H ) cout << i+pce.H<<endl;
    if (!inRangeHeight(i) || !inRangeWidth(j) ||
        !inRangeHeight(i + pce.H - 1) || !inRangeWidth(j + pce.W - 1))
      return false;

    for (int ci = i; ci <= i + pce.H - 1; ++ci) {
      for (int cj = j; cj <= j + pce.W - 1; ++cj) {
        if (m[ci][cj] == BURIED && pce.m[ci - i + 1][cj - j + 1] == PZL)
          return false;
      }
    }
    return true;
  }
  void CheckPiece(int i, int j, CPiece::piece &p) {
    CPiece::piece &pce = p;

    if (!inRangeHeight(i) || !inRangeWidth(j) ||
        !inRangeHeight(i + pce.H - 1) || !inRangeWidth(j + pce.W - 1))
      return;

    for (int ci = i; ci <= i + pce.H - 1; ++ci) {
      for (int cj = j; cj <= j + pce.W - 1; ++cj) {
        if (m[ci][cj] == NONE && pce.m[ci - i + 1][cj - j + 1] == PZL)
          chk[ci][cj] = 1;
      }
    }
  }
  void PutPiece(int i, int j, CPiece::piece &p) {
    CPiece::piece &pce = p;

    for (int ci = i; ci <= i + pce.H - 1; ++ci) {
      for (int cj = j; cj <= j + pce.W - 1; ++cj) {
        if (m[ci][cj] == NONE && pce.m[ci - i + 1][cj - j + 1] == PZL)
          m[ci][cj] = BURIED;
      }
    }
  }
  bool Complete() {
    for (int i = 1; i <= H; ++i)
      for (int j = 1; j <= W; ++j)
        if (m[i][j] == NONE)
          return false;
    return true;
  }
  int CountEmptyCells() {
    int ret = 0;
    for (int i = 1; i <= H; ++i)
      for (int j = 1; j <= W; ++j)
        if (m[i][j] == NONE)
          ++ret;
    return ret;
  }
};

bool DFS(CPuzzle &p, CPieces &ps, bool &bAbort) {
  int choose = NIL;

  // p.Print();cout<<endl;

  for (unsigned int i = 0; i < ps.vPieces.size(); ++i) {
    if (ps.bUse[i] && !ps.bUsed[i]) {
      choose = i;
      break;
    }
  }

  if (choose == NIL) {
    if (p.Complete())
      return true;
    else
      return false;
  } else if (p.Complete()) {
    bAbort = true;
    return true;
  }

  for (int k = 0; k < 4; ++k) {

    /*cout << "Considering : "<<ps.vPieces[choose].pr[k].si <<","
    <<ps.vPieces[choose].pr[k].sj<<endl; ps.vPieces[choose].pr[k].Print(); cout
    << endl;*/

    for (int i = 1; i <= p.H; ++i) {
      for (int j = 1; j <= p.W; ++j) {
        if (p.m[i][j] == NONE) {
          if (p.TryPutPiece(i - ps.vPieces[choose].pr[k].si,
                            j - ps.vPieces[choose].pr[k].sj,
                            ps.vPieces[choose].pr[k])) {
            CPuzzle pzl_tmp = p;
            bool bResult;

            /*cout << "Chosen: " << choose << " (i,j) = (" << i << "," << j <<
            ")\\n"; cout << "Piece :\\n"; ps.vPieces[choose].pr[k].Print(); cout
            << endl;*/

            pzl_tmp.ResetChk();
            if (pzl_tmp.CheckAndPutPiece(i - ps.vPieces[choose].pr[k].si,
                                         j - ps.vPieces[choose].pr[k].sj,
                                         choose, k, ps)) {
              ps.bUsed.set(choose);
              bResult = DFS(pzl_tmp, ps, bAbort);
              if (bResult)
                return true;
              ps.bUsed.reset(choose);
            }
          }
        }
      }
    }
  }
  return false;
}
int main() {
  while (true) {
    int n;
    int p, pnum;
    CPuzzle pzl;
    CPieces ps;

    pzl.Initialize();

    cin >> pzl.H >> pzl.W;

    if (pzl.H == 0 && pzl.W == 0)
      break;

    for (int i = 1; i <= pzl.H; ++i) {
      string s;
      cin >> s;
      for (int j = 1; j <= pzl.W; ++j) {
        if (s[j - 1] == '#')
          pzl.m[i][j] = BURIED;
        else
          pzl.m[i][j] = NONE;
      }
    }

    cin >> n;
    for (int i = 0; i < n; ++i) {
      CPiece tmp;

      cin >> tmp.pr[0].H >> tmp.pr[0].W;
      for (int j = 1; j <= tmp.pr[0].H; ++j) {
        string s;
        cin >> s;
        for (int k = 1; k <= tmp.pr[0].W; ++k) {
          if (s[k - 1] == '#')
            tmp.pr[0].m[j][k] = PZL;
          else
            tmp.pr[0].m[j][k] = NONE;
        }
      }
      tmp.Minimize();
      tmp.CreateRotations();
      ps.vPieces.push_back(tmp);
    }

    cin >> p;
    for (int i = 0; i < p; ++i) {
      cin >> pnum;
      bool bAbort = false;
      int cntPzl = 0;
      int cntPss = 0;
      CPuzzle pzl_tmp = pzl;
      CPieces ps_tmp;

      ps_tmp.bUse.reset();
      ps_tmp.bUsed.reset();
      for (int j = 0; j < pnum; ++j) {
        int t;
        cin >> t;
        ps_tmp.vPieces.push_back(ps.vPieces[t - 1]);
        cntPss += ps.vPieces[t - 1].CountPuzzleCells();
        ps_tmp.bUse.set(j);
      }
      cntPzl = pzl_tmp.CountEmptyCells();

      if (cntPzl != cntPss) {
        cout << "NO\\n";
        continue;
      }

      /* ツパツズツδ仰づ個妥・ツつォツつ「ツ渉づ可青ョツ療ア */
      sort(ps_tmp.vPieces.begin(), ps_tmp.vPieces.end(), greater<CPiece>());

      if (DFS(pzl_tmp, ps_tmp, bAbort))
        cout << (bAbort ? "NO\\n" : "YES\\n");
      else
        cout << "NO\\n";
    }
  }
  return 0;
}