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: Runtime Error)

#include <stdio.h>          // printf(), scanf()
#include <stdlib.h>         // qsort()
#include <string.h>         // memset(), memcpy(), strchr()
#include <stdbool.h>

// #define DEBUG 1

#define MAX_W 300
#define MAX_H 300
#define MAX_N 100

typedef struct order_tbl
{
	int s;
	int bx;
	int by;
	int angle;
	double rate;
} order_t;

const char NUL = '\0';

#ifdef DEBUG
static int O = 0;
#endif

int H, W;
char field[MAX_H][MAX_W + 1];
char puzzle[MAX_H][MAX_W + 1];
int n;
int h0[MAX_N][4];
int w0[MAX_N][4];
char piece[MAX_N][4][MAX_H][MAX_W + 1];
int k;
int t[MAX_N];

void
bury(order_t *u)
{
	int s = u->s;
	int a = u->angle;
	int h = h0[s][a];
	int w = w0[s][a];

	for (int y = 0; y < h; ++y)
	{
		for (int x = 0; x < w; ++x)
		{
			if (piece[s][a][y][x] == '#')
				field[u->by + y][u->bx + x] = '*';
		}
	}
}

double
fitin(order_t *u, int a, int bx, int by)
{
	int s = u->s;
	int h = h0[s][a];
	int w = w0[s][a];

	int dx[4] = { 0, 1, 0,-1};
	int dy[4] = { 1, 0,-1, 0};

	int count = 0;
	int total = 0;
	for (int x = -1; x <= w; ++x)
	{
		int nx = bx + x;
		for (int y = -1; y <= h; ++y)
		{
			int ny = by + y;
			if (0 <= x && x < w && 0 <= y && y < h && piece[s][a][y][x] == '#')
			{
				if (field[ny][nx] != '.')
					return -100.0;
			}
			else // piece[s][a][y][x] == '.' ?
			{
				int i;
				for (i = 0; i < 4; ++i)
				{
					int tx = x + dx[i], ty = y + dy[i];
					if (0 <= tx && tx < w && 0 <= ty && ty < h && piece[s][a][ty][tx] == '#')
						break;
				}

				if (i < 4)
				{
					total++;
					if (nx < 0 || W <= nx || ny < 0 || H <= ny || field[ny][nx] != '.')
						count++;
				}
			}
		}
	}

	return count * 100.0 / total;
}

void
probe(order_t *u)
{
	int s = u->s;
	for (int a = 0; a < 4; ++a)
	{
		int h = h0[s][a];
		int w = w0[s][a];

		int fx = strchr(piece[s][a][0], '#') - piece[s][a][0];
		for (int by = 0; by + h <= H; ++by)
		{
			for (int bx = 0; bx + w <= W; ++bx)
			{
				if (field[by][bx + fx] == '.')
				{
#ifdef DEBUG
					O++;
#endif
					double r = fitin(u, a, bx, by);
					if (r > u->rate)
					{
						u->rate = r;
						u->bx = bx;
						u->by = by;
						u->angle = a;

						if (u->rate >= 100.0)
						{
							bury(u);
							return;
						}
					}
				}
			}
		}
	}
}

int
cmp_func(const void *l_, const void *r_)
{
	const order_t *l = (const order_t*) l_;
	const order_t *r = (const order_t*) r_;

	if (l->rate < r->rate)
		return 1;

	if (l->rate > r->rate)
		return -1;

	return 0;
}

bool
solve()
{
	order_t u;
	order_t order[MAX_N];
	int memo[MAX_N];
	int ix, ix2;

	memcpy(field, puzzle, sizeof(field));
	ix = 0;
	for (int i = 0; i < k; ++i)
		memo[ix++] = t[i];

	while (ix != 0)
	{
		ix2 = 0;
		for (int i = 0; i < ix; ++i)
		{
#ifdef DEBUG
			memset(&u, 0x00, sizeof(u));
#endif
			u.s = memo[i];
			u.rate = -100.0;
			probe(&u);
			if (u.rate != 100.0)
				order[ix2++] = u;
		}

		if (ix2 == 0)
			break;

		qsort(order, ix2, sizeof(order_t), cmp_func);
		if (order[0].rate == -100.0)
			return false;

		bury(&order[0]);

		ix = 0;
		for (int i = 1; i < ix2; ++i)
			memo[ix++] = order[i].s;
	}

	for (int y = 0; y < H; ++y)
	{
		for (int x = 0; x < W; ++x)
		{
			if (field[y][x] == '.')
				return false;
		}
	}

	return true;
}

int
main(int argc, char **argv)
{
	while (true)
	{
		scanf("%d%d\n", &H, &W);
		if (H == 0 && W == 0)
			break;

		for (int i = 0; i < H; ++i)
			scanf("%s", &puzzle[i][0]);

		scanf("%d", &n);
		for (int s = 0; s < n; ++s)
		{
			scanf("%d%d\n", &h0[s][0], &w0[s][0]);
			int h = h0[s][0];
			int w = w0[s][0];

			for (int y = 0; y < h; ++y)
				scanf("%s", &piece[s][0][y][0]);

			h0[s][1] = w;
			w0[s][1] = h;
			for (int y = 0; y < h; ++y)
			{
				for (int x = 0; x < w; ++x)
					piece[s][1][x][h - y - 1] = piece[s][0][y][x];
			}

#ifdef DEBUG
			for (int x = 0; x < w; ++x)
				piece[s][1][x][h] = NUL;
#endif

			h0[s][2] = h;
			w0[s][2] = w;
			for (int y = 0; y < h; ++y)
			{
				for (int x = 0; x < w; ++x)
					piece[s][2][h - 1 - y][w - 1 - x] = piece[s][0][y][x];

#ifdef DEBUG
				piece[s][2][h - 1 - y][w] = NUL;
#endif
			}

			h0[s][3] = w;
			w0[s][3] = h;
			for (int y = 0; y < h; ++y)
			{
				for (int x = 0; x < w; ++x)
					piece[s][3][w - 1 - x][y] = piece[s][0][y][x];
			}

#ifdef DEBUG
			for (int x = 0; x < w; ++x)
				piece[s][3][x][h] = NUL;
#endif
		}

		int p;
		scanf("%d\n", &p);
		for (int i = 0; i < p; ++i)
		{
			scanf("%d", &k);
			for (int j = 0; j < k; ++j)
			{
				scanf("%d", &t[j]);
				t[j]--;
			}

			printf("%s\n", solve() ? "YES" : "NO");
		}
	}

#ifdef DEBUG
	fprintf(stderr, "O:%d\n", O);
#endif
	return 0;
}