Problem:
ジグソーパズル

子供から大人まで脳トレ系パズルゲームが流行しています。我々も遅れを取らぬよう、パズルゲームを作ってみんなで遊ぶことにしました。

我々が考えたのはジグソーパズルのゲームで、未完成の部分を埋めるのに必要なピースを選ぶというものです。図 1 (a) はパズルの枠の例です。黒が埋まっている部分、白が未完成の部分です。このパズルを完成するのに使えるピースが図 1 (b) のように与えられます。この中から、枠の白い部分を埋めることができる黒いピースを 1 つ以上選択します。例えば、図 2 の選択例 1 のような組み合わせなら正解となります。一方、選択例 2 のような組み合わせではパズルは完成しないので不正解となります。また、選択したピースが余ってしまう場合も不正解です。このように、プレイヤーは適切なピースを選択することでゲームをクリアします。

そこでこのパズルゲームで用いる判定プログラムを開発することになりました。未完成のパズル、ピースの候補、そしてプレイヤーが選んだピースの組み合わせを入力とし、プレイヤーが適切なピースを選ぶことができていれば YES を、そうでなければ NO と出力するプログラムを作成してください。

この問題では、パズルの枠は H × W の配列で表し、未完成の部分を . (半角ピリオド)、完成している部分を # (半角シャープ)によって与えます。パズルの枠の大きさは最大 20 × 20 とします。また、各ピースは h × w の配列で表し、ピースを構成する部分を # 、そうでない部分を . によって与えます。与えられる各ピースは、元の状態から 90 度、180 度、270 度だけ回転することができます。また、各ピースの大きさは最大 20 × 20 とし、与えられるピースの数 n は最大 10 とします。

Input

複数のデータセットが与えられます。各データセットは以下の形式で与えられます。

H W
g1,1g1,2...g1,W
g2,1g2,2...g2,W
:
gH,1gH,2...gH,W
n
h1 w1
c11,1c11,2...c11,w1
c12,1c12,2...c12,w1
:
c1h1,1c1h1,2...c1h1,w1
:
:
hn wn
cn1,1cn1,2...cn1,wn
cn2,1cn2,2...cn2,wn
:
cnhn,1cnhn,2...cnhn,wn
p
k1 t1 t2 ... tk1
k2 t1 t2 ... tk2
:
kp t1 t2 ... tkp

1 行目に、パズルの枠の大きさ H(縦) と W(横) が与えられます。
2 行目に、文字 gi,j (. または #) からなりパズルの盤面を表す 1 行 W 文字の文字列が H 行与えられます。

続いてピースの数 n、n 個のピースの情報が与えられます。各ピースの情報として、l 番目のピースの配列のサイズ hl (縦) と wl (横)、l 番目のピースの配列が与えられます。l 番目のピースの配列として文字 cli,j (. または #) からなる 1 行 wl 文字の文字列が hl 行与えられます。

続いてプレイヤーの人数 p、i 番目のプレイヤーの選択したピースの数 ki と選択したピースの番号 tj が与えられます。

入力は２つの 0 を含む行で終了します。データセットの数は 10 を超えません。

Output

各データセットごとに、i 番目のプレイヤーが選択したピースの正否 YES または NO を i 行目に出力してください。

Sample Input

14 20
####################
###.............####
####..........######
#######.....########
########.....#######
###..###......######
###..####......#####
#########......#####
###########.....####
############.....###
###.########......##
###.#######...###.##
##...###....#####.##
####################
10
12 15
#############..
.##########....
....#####......
.....#####.....
.....######....
......######...
......######...
........#####..
.........#####.
.........######
........###...#
.....####.....#
3 3
#..
###
#..
2 2
##
##
4 10
....#####.
....######
...###...#
####.....#
6 5
....#
..###
#####
##.##
#..##
#..#.
6 4
...#
.###
####
##.#
##.#
#...
2 6
######
.#####
2 7
..#####
#######
2 13
#############
.##########..
6 9
#####....
.######..
.######..
..######.
...#####.
....#####
8
3 1 2 3
4 1 2 3 4
7 2 3 4 5 6 7 8
5 2 3 10 7 8
6 2 3 9 5 6 4
8 2 3 4 6 9 5 4 10
4 4 5 6 9
5 10 2 3 4 9
0 0

Output for the Sample Input

YES
NO
YES
NO
YES
NO
NO
YES

Solution in C# (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Piece
    {
        internal List<int[,]> dir;
        internal int size;

        public Piece()
        {
            dir = new List<int[,]>();
        }
    }

    class Puzzle
    {
        readonly int H, W;

        int[,] map;
        int[,] state;
        Piece[] pieces;
        Piece[] selected;

        int selectVolume;

        public Puzzle(int H, int W)
        {
            this.H = H;
            this.W = W;

            map = new int[H, W];
        }

        public void MakeMap()
        {
            for (int i = 0; i < H; i++)
            {
                string input = Console.ReadLine();

                for (int j = 0; j < W; j++)
                {
                    map[i, j] = input[j] == '#' ? 1 : 0;
                }
            }
        }

        public void SetPiecesMemory(int n)
        {
            pieces = new Piece[n + 1];

            for (int i = 1; i <= n; i++)
            {
                pieces[i] = new Piece();
            }
        }

        public void MakePiece(int id)
        {
            string[] input1 = Console.ReadLine().Split(' ');
            int h = int.Parse(input1[0]);
            int w = int.Parse(input1[1]);

            int[,] original = new int[h, w];

            for (int i = 0; i < h; i++)
            {
                string input2 = Console.ReadLine();

                for (int j = 0; j < w; j++)
                {
                    original[i, j] = input2[j] == '#' ? 1 : 0;
                }
            }

            int[,] right = new int[w, h];
            int[,] rev = new int[h, w];
            int[,] left = new int[w, h];

            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                {
                    right[j, h - i - 1] = original[i, j];
                    rev[h - i - 1, w - j - 1] = original[i, j];
                    left[w - j - 1, i] = original[i, j];
                }
            }
            pieces[id].size = h * w;
            pieces[id].dir.Add(original);
            pieces[id].dir.Add(right);
            pieces[id].dir.Add(rev);
            pieces[id].dir.Add(left);
        }

        public void SelectPieces()
        {
            int[] input = Array.ConvertAll(Console.ReadLine().Split(' '), int.Parse);

            selectVolume = input[0];

            selected = new Piece[selectVolume];

            for (int i = 0; i < selectVolume; i++)
            {
                selected[i] = new Piece();
                selected[i].size = pieces[input[i + 1]].size;

                for (int j = 0; j < 4; j++)
                {
                    selected[i].dir.Add(pieces[input[i + 1]].dir[j]);
                }
            }
        }

        public bool Solve()
        {
            state = (int[,])map.Clone();

            Array.Sort(selected, (a, b) => b.size - a.size);

            return DFS(0);
        }

        private bool DFS(int depth)
        {
            if (depth == selectVolume)
            {
                if (CheckClear()) return true;
                else return false;
            }

            foreach (var piece in selected[depth].dir)
            {
                int h = piece.GetUpperBound(0);
                int w = piece.GetUpperBound(1);

                for (int i = 0; i < H - h; i++)
                {
                    for (int j = 0; j < W - w; j++)
                    {
                        if (!CheckPiece(piece, j, i)) continue;

                        for (int y = 0; y <= h; y++)
                        {
                            for (int x = 0; x <= w; x++)
                            {
                                state[i + y, j + x] += piece[y, x];
                            }
                        }

                        if (DFS(depth + 1)) return true;

                        for (int y = 0; y <= h; y++)
                        {
                            for (int x = 0; x <= w; x++)
                            {
                                state[i + y, j + x] -= piece[y, x];
                            }
                        }
                    }
                }
            }
            return false;
        }

        private bool CheckClear()
        {
            for (int i = 0; i < H; i++)
            {
                for (int j = 0; j < W; j++)
                {
                    if (state[i, j] != 1) return false;
                }
            }
            return true;
        }

        private bool CheckPiece(int[,] piece, int x, int y)
        {
            int h = piece.GetUpperBound(0);
            int w = piece.GetUpperBound(1);

            for (int i = 0; i <= h; i++)
            {
                for (int j = 0; j <= w; j++)
                {
                    if (piece[i, j] == 1)
                    {
                        if (state[y + i, x + j] == 1) return false;
                    }
                }
            }
            return true;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            StringBuilder sb = new StringBuilder();

            while (true)
            {
                string[] input = Console.ReadLine().Split(' ');
                int H = int.Parse(input[0]);
                int W = int.Parse(input[1]);

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

                Puzzle pz = new Puzzle(H, W);

                pz.MakeMap();

                int n = int.Parse(Console.ReadLine());

                pz.SetPiecesMemory(n);

                for (int i = 1; i <= n; i++)
                {
                    pz.MakePiece(i);
                }

                int p = int.Parse(Console.ReadLine());

                for (int i = 0; i < p; i++)
                {
                    pz.SelectPieces();
                    sb.AppendLine(pz.Solve() ? "YES" : "NO");
                }
            }
            Console.Write(sb);
        }
    }
}