Problem:
Problem I:
Crystal Jails
Artistic Crystal Manufacture developed products named Crystal Jails. They are cool ornaments
forming a rectangular solid. They consist of colorful crystal cubes. There are bright cores on the
center of cubes, which are the origin of the name. The combination of various colored reflections
shows fantastic dance of lights.
The company wanted to make big sales with Crystal Jails. They thought nice-looking color
patterns were the most important factor for attractive products. If they could provide several
nice patterns, some customers would buy more than one products. However, they didn't have
staff who could design nice patterns. So they hired a temporary designer to decide the patterns.
The color pattern for mass production had a technical limitation: all cubes of the same color
must be connected. In addition, they needed to send the pattern to the factory as a set of
blocks
,
i.e. shapes formed by cubes of the same color. They requested him to represent the design in
this form.
After a week of work, he sent various ideas of the color patterns to them. At first, his designs
looked nice, but they noticed some patterns couldn’t form a rectangular solid. He was a good
designer, but they had not noticed he lacked space geometrical sense.
They didn't have time to ask him to revise his design. Although it was acceptable to ignore bad
patterns, it also took a lot of time to figure out all bad patterns manually. So the leader of this
project decided to ask you, a freelance programmer, for help.
Your task is to write a program to judge whether a pattern can form a rectangular solid. Note
that blocks can be rotated.
Input
The input consists of multiple datasets. Each dataset is formatted as follows:
W D H N
Block
1
Block
2
...
Block
N
The first line of a dataset contains four positive integers
W
,
D
,
H
and
N
.
W
,
D
and
H
indicate
the width, depth and height of a Crystal Jail.
N
indicates the number of colors.
The remaining lines describe
N
colored blocks. Each description is formatted as follows:
w d h
c
111
c
211
...
c
w
11
c
121
c
221
...
c
w
21
...
c
1
d
1
c
2
d
1
...
c
wd
1
c
112
c
212
...
c
w
12
c
122
c
222
...
c
w
22
...
c
1
d
2
c
2
d
2
...
c
wd
2
.
.
.
c
11
h
c
21
h
...
c
w
1
h
c
12
h
c
22
h
...
c
w
2
h
...
c
1
dh
c
2
dh
...
c
wdh
The first line of the description contains three positive integers
w
,
d
and
h
, which indicate the
width, depth and height of the block. The following (
d
+ 1) ×
h
lines describe the shape of
the block. They show the cross-section layout of crystal cubes from bottom to top. On each
height, the layout is described as
d
lines of
w
characters. Each character
c
xyz
is either '
*
' or '
.
'.
'
*
' indicates there is a crystal cube on that space, and '
.
' indicates there is not. A blank line
follows after each (
d
×
w
)-matrix.
The input is terminated by a line containing four zeros.
You can assume the followings.
1 ≤
W
,
D
,
H
,
w
,
d
,
h
≤ 3.
1 ≤
N
≤ 27.
Each block has at least one crystal cubes and 
...(truncated)

Submitted solutions:

code_snippet: #include<stdio.h>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>

using namespace std;
char in[5][5][5];
char tmp[5][5][5];
int bit[30][24];
int mw[30][24];
int md[30][24];
int mh[30][24];
int SZ[30];

int W,D,H;
int w,d,h;
const int D_MAX_V=30;
const int D_v_size=30;
struct D_wolf{
	int t,c,r;
	D_wolf(){t=c=r=0;}
	D_wolf(int t1,int c1,int r1){
		t=t1;c=c1;r=r1;
	}
};
vector<D_wolf>D_G[D_MAX_V];
int D_level[D_MAX_V];
int D_iter[D_MAX_V];

void add_edge(int from,int to,int cap){
	D_G[from].push_back(D_wolf(to,cap,D_G[to].size()));
	D_G[to].push_back(D_wolf(from,0,D_G[from].size()-1));
}
void D_bfs(int s){
	for(int i=0;i<D_v_size;i++)D_level[i]=-1;
	queue<int> Q;
	D_level[s]=0;
	Q.push(s);
	while(Q.size()){
		int v=Q.front();
		Q.pop();
		for(int i=0;i<D_G[v].size();i++){
			if(D_G[v][i].c>0&&D_level[D_G[v][i].t]<0){
				D_level[D_G[v][i].t]=D_level[v]+1;
				Q.push(D_G[v][i].t);
			}
		}
	}
}
int D_dfs(int v,int t,int f){
	if(v==t)return f;
	for(;D_iter[v]<D_G[v].size();D_iter[v]++){
		int i=D_iter[v];
		if(D_G[v][i].c>0&&D_level[v]<D_level[D_G[v][i].t]){
			int d=D_dfs(D_G[v][i].t,t,min(f,D_G[v][i].c));
			if(d>0){
				D_G[v][i].c-=d;
				D_G[D_G[v][i].t][D_G[v][i].r].c+=d;
				return d;
			}
		}
	}
	return 0;
}
int max_flow(int s,int t){
	int flow=0;
	for(;;){
		D_bfs(s);
		if(D_level[t]<0)return flow;
		for(int i=0;i<D_v_size;i++)D_iter[i]=0;
		int f;
		while((f=D_dfs(s,t,99999999))>0){flow+=f;}
	}
	return 0;
}
int dx[]={1,-1,0,0,0,0};
int dy[]={0,0,1,-1,0,0};
int dz[]={0,0,0,0,1,-1};
int check(int a){
	for(int i=0;i<D_MAX_V;i++){
		D_G[i].clear();D_level[i]=D_iter[i]=0;
	}
	int S=W*H*D;
	int T=W*H*D+1;
	for(int i=0;i<H;i++){
		for(int j=0;j<D;j++){
			for(int k=0;k<W;k++){
				if(a&(1<<(i*D*W+j*W+k)))continue;
				if((i+j+k)%2){
					add_edge(i*D*W+j*W+k,T,1);
					continue;
				}
				add_edge(S,i*D*W+j*W+k,1);
				for(int l=0;l<6;l++){
					int ti=i+dx[l];
					int tj=j+dy[l];
					int tk=k+dz[l];
					if(ti<0||ti>=H||tj<0||tj>=D||tk<0||tk>=W)continue;
					if(a&(1<<(ti*D*W+tj*W+tk)))continue;
					add_edge(i*D*W+j*W+k,ti*D*W+tj*W+tk,1);
				}
			}
		}
	}
	return max_flow(S,T);
}
void right(){
	for(int i=0;i<h;i++)for(int j=0;j<d;j++)for(int k=0;k<w;k++)
		tmp[i][k][d-1-j]=in[i][j][k];
	swap(d,w);
	for(int i=0;i<h;i++)for(int j=0;j<d;j++)for(int k=0;k<w;k++)
		in[i][j][k]=tmp[i][j][k];
}
void front(){
	for(int i=0;i<h;i++)for(int j=0;j<d;j++)for(int k=0;k<w;k++)
		tmp[d-1-j][i][k]=in[i][j][k];
	swap(h,d);
	for(int i=0;i<h;i++)for(int j=0;j<d;j++)for(int k=0;k<w;k++)
		in[i][j][k]=tmp[i][j][k];
}
int calc(){
	int ret=0;
	for(int i=0;i<h;i++)for(int j=0;j<d;j++)for(int k=0;k<w;k++){
		if(in[i][j][k]=='*')ret+=1<<(i*D*W+j*W+k);
	}
	return ret;
}
int n;
pair<int,int>ev[30];
set<int>vis;
int has[30];
int twos;
int ch[30];
int dfs(int a,int b){
	if(a==n){
		int mat=check(b);
	//	printf("%d %d\n",b,mat);
		if(mat>=twos)return 1;
		else return 0;
	}
	if(vis.count(b))return 0;
	int at=ev[a].second;
	if(SZ[at]==0)return 0;
	if(has[at]<=2){
		return dfs(a+1,b);
	}
	int black=0;
	int white=0;
	int pos=ch[a];
	for(int i=0;i<W*H*D;i++)if(!(b&(1<<i))){
		if((i/(W*H)+i%(W*H)/W+i%W)%2)black++;
		else white++;
	}
	for(int i=0;i<a;i++)if(has[ev[i].second]==1)pos++;
	if(max(black-white,white-black)>pos){vis.insert(b);return 0;}
	for(int i=0;i<SZ[at];i++){
		if(a==0&&W==H&&H==D&&i>0)break;
		if(i&&bit[at][i]==bit[at][i-1])continue;
		for(int j=0;j<=H-mh[at][i];j++){
			for(int k=0;k<=D-md[at][i];k++){
				for(int l=0;l<=W-mw[at][i];l++){
					int val=bit[at][i]<<(j*D*W+k*W+l);
					if(b&val)continue;
					if(dfs(a+1,b+val)){
						return 1;
					}
				}
			}
		}
	}
	vis.insert(b);
	return 0;
}
int main(){
	int a,b,c;
	while(scanf("%d%d%d%d",&a,&b,&c,&n),n){
		vis.clear();
		W=a;D=b;H=c;
		twos=0;
		for(int i=0;i<30;i++)for(int j=0;j<24;j++){
			bit[i][j]=mw[i][j]=md[i][j]=mh[i][j]=0;
		}
		for(int i=0;i<30;i++)has[i]=0;
		int tot=0;
		for(int i=0;i<n;i++){
			scanf("%d%d%d",&w,&d,&h);
			for(int j=0;j<h;j++){
				for(int k=0;k<d;k++){
					scanf("%s",in[j][k]);
					for(int l=0;l<w;l++)if(in[j][k][l]=='*')has[i]++;
				}
			}
			if(has[i]==2)twos++;
			while(1){
				bool chk=true;
				for(int j=0;j<d;j++)for(int k=0;k<w;k++)if(in[0][j][k]=='*')chk=false;
				if(!chk)break;
				for(int j=1;j<h;j++)for(int k=0;k<d;k++)for(int l=0;l<w;l++)in[j-1][k][l]=in[j][k][l];
				h--;
			}
			while(1){
				bool chk=true;
				for(int j=0;j<d;j++)for(int k=0;k<w;k++)if(in[h-1][j][k]=='*')chk=false;
				if(!chk)break;
				h--;
			}
			while(1){
				bool chk=true;
				for(int j=0;j<h;j++)for(int k=0;k<w;k++)if(in[j][0][k]=='*')chk=false;
				if(!chk)break;
				for(int j=0;j<h;j++)for(int k=1;k<d;k++)for(int l=0;l<w;l++)in[j][k-1][l]=in[j][k][l];
				d--;
			}
			while(1){
				bool chk=true;
				for(int j=0;j<h;j++)for(int k=0;k<w;k++)if(in[j][d-1][k]=='*')chk=false;
				if(!chk)break;
				d--;
			}
			while(1){
				bool chk=true;
				for(int j=0;j<h;j++)for(int k=0;k<d;k++)if(in[j][k][0]=='*')chk=false;
				if(!chk)break;
				for(int j=0;j<h;j++)for(int k=0;k<d;k++)for(int l=1;l<w;l++)in[j][k][l-1]=in[j][k][l];
				w--;
			}
			while(1){
				bool chk=true;
				for(int j=0;j<h;j++)for(int k=0;k<d;k++)if(in[j][k][w-1]=='*')chk=false;
				if(!chk)break;
				w--;
			}
			int sz=0;
			for(int j=0;j<4;j++){
				for(int k=0;k<4;k++){
					if(w<=W&&d<=D&&h<=H)bit[i][sz++]=calc();
					right();
				}
				front();
			}right();front();
			for(int j=0;j<4;j++){
				if(w<=W&&d<=D&&h<=H)bit[i][sz++]=calc();
				right();
			}
			front();front();
			for(int j=0;j<4;j++){
				if(w<=W&&d<=D&&h<=H)bit[i][sz++]=calc();
				right();
			}
			for(int j=0;j<sz;j++){
				//printf("%d ",bit[i][j]);
				while(bit[i][j]%(1<<(W*D))==0){
					bit[i][j]/=(1<<(W*D));
				}
				int td=0;for(int k=0;k<H;k++)td+=(((1<<W)-1)<<(k*D*W));
				while((td&bit[i][j])==0){
					bit[i][j]/=(1<<W);
				}
				int tw=0;for(int k=0;k<H;k++)for(int l=0;l<D;l++)tw+=(1<<(k*D*W+l*W));
			//	printf("%d\n",tw);
				while((tw&bit[i][j])==0){
					bit[i][j]/=2;
				}
			}//printf("\n");
			std::sort(bit[i],bit[i]+sz);
			for(int j=0;j<sz;j++){
				for(int k=0;k<H;k++)for(int l=0;l<D;l++)for(int o=0;o<W;o++)
					if(bit[i][j]&(1<<(k*D*W+l*W+o))){
						mh[i][j]=max(mh[i][j],k+1);
						md[i][j]=max(md[i][j],l+1);
						mw[i][j]=max(mw[i][j],o+1);
					}
			}
			SZ[i]=sz;
		}
		for(int i=0;i<n;i++){
			int sum=0;
			for(int j=0;j<SZ[i];j++){
				if(j&&bit[i][j]==bit[i][j-1])continue;
				//printf("%d ",bit[i][j]);
				sum+=(H-mh[i][j]+1)*(W-mw[i][j]+1)*(D-md[i][j]+1);
			}//printf("\n");
			ev[i]=make_pair(-has[i],i);
		}
	//	printf("do\n");
		std::sort(ev,ev+n);
		
		int bw=0;
		for(int i=n-1;i>=0;i--){
			if(SZ[i]==0)continue;
			int black=0;
			int white=0;
			for(int j=0;j<mh[i][0];j++)for(int k=0;k<md[i][0];k++)for(int l=0;l<mw[i][0];l++)
				if(bit[i][0]&(1<<(j*D*W+k*W+l))){
					if((j+k+l)%2)black++;
					else white++;
				}
			bw+=max(black-white,white-black);
			ch[i]=bw;
		}
		if(dfs(0,0))printf("Yes\n");
		else printf("No\n");
	}
}
accuracy: 1
time_ms: 780
memory_kb: 7992
final_rank: 1

code_snippet: #include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<iostream>
#include<bitset>
#include<algorithm>

using namespace std;

template<class T> inline void chmin(T &a,T b){
	a=min(a,b);
}
template<class T> inline void chmax(T &a,T &b){
	a=max(a,b);
}

string getBin(int n){
	string res="";
/*	for(int i=26;i>=0;i--){
		if((n>>i)&1) res+='1';
		else res+='0';
		if(i>0&&i%9==0) res+=' ';
	}*/
	for(int i=0;i<27;i++){
		if((n>>i)&1) res+='1';
		else res+='0';
		if(i==8||i==17) res+=' ';
	}
	return res;
}

int id=0;
bool cur_block[24][3][3][3];
bool cur[3][3][3];
bool tmp[3][3][3];

int encode_(){
	int c=0;
	int res=0;
	for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
		if(cur[i][j][k]) res|=(1<<c);
		c++;
	}
	return res;
}

void put(){
	int enc=0;
	int c=0;
	for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
		cur_block[id][i][j][k]=cur[i][j][k];
		if(cur[i][j][k]) enc|=(1<<c);
		c++;
	}
	id++;
//	cerr<<"id="<<id<<"\n";
//	cerr<<getBin(enc)<<"\n";
}

void cp(){
	for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
		cur[i][j][k]=tmp[i][j][k];
	}
}

void rot3(){
	for(int x=0;x<2;x++){
		for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
			tmp[2-j][2-i][2-k]=cur[i][j][k];
		}
		cp();
		put();
	}
}

void rot2(){
	for(int x=0;x<3;x++){
		for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
			tmp[j][k][i]=cur[i][j][k];
		}
		cp();
		rot3();
	}
}

void rot1(){
	for(int x=0;x<4;x++){
		for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
			tmp[2-j][i][k]=cur[i][j][k];
		}
		cp();
		rot2();
	}
}

int csum;
vector<int> cur_block_encode;
int goal;

void encode(int id){
	int c=0;
	int res=0;
	int mini=3,minj=3,mink=3;
	int maxi=-1,maxj=-1,maxk=-1;
	for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
		if(cur_block[id][i][j][k]){
			chmin(mini,i);
			chmin(minj,j);
			chmin(mink,k);
			chmax(maxi,i);
			chmax(maxj,j);
			chmax(maxk,k);
		}
	}
	memset(cur,false,sizeof(cur));
	for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
		cur[i][j][k]=(i+mini<3&&j+minj<3&&k+mink<3)?cur_block[id][i+mini][j+minj][k+mink]:false;
	}
	for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
		if(cur[i][j][k]) res|=(1<<c);
		c++;
	}
//	cur_block_encode.push_back(res);
	csum=maxi+maxj+maxk-mini-minj-mink+3;
	int I=3-(maxi-mini+1),J=3-(maxj-minj+1),K=3-(maxk-mink+1);
	for(int mi=0;mi<=I;mi++) for(int mj=0;mj<=J;mj++) for(int mk=0;mk<=K;mk++){
	//	int x=9*mk+3*mi+mj;
		int x=mk+3*mj+9*mi;
		if(((res<<x)&goal)!=(res<<x)) continue;
		cur_block_encode.push_back(res<<x);
	}
//	return res;
}

void encode(){
	cur_block_encode.clear();
	for(int i=0;i<24;i++){
//		int cur_encode=encode(i);
//		if((goal&cur_encode)==cur_encode) cur_block_encode.push_back(cur_encode);
		encode(i);
	}
	sort(cur_block_encode.begin(),cur_block_encode.end());
	cur_block_encode.erase(unique(cur_block_encode.begin(),cur_block_encode.end()),cur_block_encode.end());
}

struct Block{
	int weight;
	int sum;//W+H+D
	vector<int> nums;
};

bool operator<(const Block &b1,const Block &b2){
	if(b1.weight!=b2.weight) return b1.weight<b2.weight;
	return b1.sum<b2.sum;
}

int W,H,D;

int N;

void inputGoal(){
	scanf("%d%d%d",&W,&D,&H);
	if(W==0&&D==0&&H==0) exit(0);
	goal=0;
	int c=0;
	for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++){
		if(i<H&&j<W&&k<D) goal|=(1<<c);
		c++;
	}
//	cerr<<getBin(goal)<<"\n";
}

vector<Block> blocks;

void inputBlock(){
	memset(cur_block,false,sizeof(cur_block));
	memset(cur,false,sizeof(cur));
	memset(tmp,false,sizeof(tmp));
	int w,d,h;
	int weight=0;
	scanf("%d%d%d",&w,&d,&h);
	char ch[10];
	for(int i=0;i<h;i++) for(int j=0;j<d;j++){
		scanf("%s",ch);
		for(int k=0;k<w;k++){
			cur[h-1-i][k][j]=ch[k]=='*';
			if(ch[k]=='*') weight++;
		}
	}
	int a=encode_();
//	cerr<<"init="<<getBin(a)<<"\n";
	if(weight==1) return;
	id=0;
	rot1();
	encode();
	Block b;
	b.nums=cur_block_encode;
	b.sum=csum;
	b.weight=weight;
	blocks.push_back(b);
//	cerr<<"enc = "<<getBin(b.nums[0])<<"\n";
//	cerr<<weight<<"\n";
}

void inputBlocks(){
	blocks.clear();
	scanf("%d",&N);
	for(int i=0;i<N;i++) inputBlock();
}

bitset<(1<<27)> calculated,memo;

bool dfs(int id,int curVal){
	if(calculated[curVal]) return memo[curVal];
//	cerr<<"id="<<id<<"val="<<getBin(curVal)<<"\n";
	if(id==blocks.size()){
		calculated[curVal]=true;
		memo[curVal]=true;
		return true;
	}
	vector<int> &nums=blocks[id].nums;
	for(int i=0;i<nums.size();i++){
		if(curVal&nums[i]) continue;
		bool flg=dfs(id+1,curVal|nums[i]);
		if(flg){
			calculated[curVal]=true;
			memo[curVal]=true;
			return true;
		}
	}
	calculated[curVal]=true;
	memo[curVal]=false;
	return false;
}

bool solve(){
	sort(blocks.begin(),blocks.end());
	reverse(blocks.begin(),blocks.end());
	calculated.reset();
	memo.reset();
	/*for(int i=0;i<blocks.size();i++){
		cerr<<"i="<<i<<"\n";
		for(int j=0;j<blocks[i].nums.size();j++){
			int n=blocks[i].nums[j];
			cerr<<getBin(n)<<"\n";
		}
		cerr<<"\n";
	}*/
	bool res=dfs(0,0);
	return res;
}

int main(){
	while(true){
		inputGoal();
		inputBlocks();
		bool ans=solve();
		if(ans) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
accuracy: 1
time_ms: 4540
memory_kb: 33992
final_rank: 3

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <set>
#include <queue>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

const int dx[6] = { 1, -1, 0, 0, 0, 0 };
const int dy[6] = { 0, 0, 1, -1, 0, 0 };
const int dz[6] = { 0, 0, 0, 0, 1, -1 };

typedef int Weight;
struct Edge {
  int src;
  int dest;
  Weight weight;
  Edge(int src, int dest, Weight weight) : src(src), dest(dest), weight(weight) {;}
  bool operator<(const Edge &rhs) const {
    if (weight != rhs.weight) { return weight > rhs.weight; }
    if (src != rhs.src) { return src < rhs.src; }
    return dest < rhs.dest;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void printMatrix(const Matrix &matrix) {
  for (int y = 0; y < (int)matrix.size(); y++) {
    for (int x = 0; x < (int)matrix[y].size(); x++) {
      printf("%d ", matrix[y][x]);
    }
    puts("");
  }
}

Weight augment(const Graph &g, Matrix &capacity, const vector<int> &level, vector<bool> &finished, int from, int t, Weight cur) {
  if (from == t || cur == 0) { return cur; }
  if (finished[from]) { return 0; }
  for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
    int to = it->dest;
    if (level[to] <= level[from]) { continue; }
    Weight f = augment(g, capacity, level, finished, to, t, min(cur, capacity[from][to]));
    if (f > 0) {
      capacity[from][to] -= f;
      capacity[to][from] += f;
      return f;
    }
  }
  finished[from] = true;
  return 0;
}

Weight MaxFlow(const Graph &g, int s, int t) {
  int n = g.size();
  Matrix capacity(n, Array(n));
  for (int from = 0; from < n; from++) {
    for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
      int to = it->dest;
      capacity[from][to] += it->weight;
    }
  }
  int ans = 0;
  while (true) {
    vector<int> level(n, -1);
    level[s] = 0;
    queue<int> que;
    que.push(s);
    for (int d = n; !que.empty() && level[que.front()] < d; ) {
      int from = que.front();
      que.pop();
      if (from == t) { d = level[from]; }
      for (Edges::const_iterator it = g[from].begin(); it != g[from].end(); it++) {
        int to = it->dest;
        if (capacity[from][to] > 0 && level[to] == -1) {
          que.push(to);
          level[to] = level[from] + 1;
        }
      }
    }
    vector<bool> finished(n);
    bool end = true;
    while (true) {
      Weight f = augment(g, capacity, level, finished, s, t, 1000000000);
      if (f == 0) { break; }
      ans += f;
      end = false;
    }
    if (end) { break; }
  }
  return ans;
}

void printState(int enc);

struct Block {
  int size;
  bool block[3][3][3];
  Block() : size(0) {
    MEMSET(block, false);
  }
  Block RotateX() {
    Block ret = *this;
    REP(x, 3) {
      ret.block[x][0][0] = block[x][2][0];
      ret.block[x][2][0] = block[x][2][2];
      ret.block[x][2][2] = block[x][0][2];
      ret.block[x][0][2] = block[x][0][0];
      ret.block[x][1][0] = block[x][2][1];
      ret.block[x][2][1] = block[x][1][2];
      ret.block[x][1][2] = block[x][0][1];
      ret.block[x][0][1] = block[x][1][0];
    }
    return ret;
  }
  Block RotateY() {
    Block ret = *this;
    REP(y, 3) {
      ret.block[0][y][0] = block[2][y][0];
      ret.block[2][y][0] = block[2][y][2];
      ret.block[2][y][2] = block[0][y][2];
      ret.block[0][y][2] = block[0][y][0];
      ret.block[1][y][0] = block[2][y][1];
      ret.block[2][y][1] = block[1][y][2];
      ret.block[1][y][2] = block[0][y][1];
      ret.block[0][y][1] = block[1][y][0];
    }
    return ret;
  }
  Block RotateZ() {
    Block ret = *this;
    REP(z, 3) {
      ret.block[0][0][z] = block[2][0][z];
      ret.block[2][0][z] = block[2][2][z];
      ret.block[2][2][z] = block[0][2][z];
      ret.block[0][2][z] = block[0][0][z];
      ret.block[1][0][z] = block[2][1][z];
      ret.block[2][1][z] = block[1][2][z];
      ret.block[1][2][z] = block[0][1][z];
      ret.block[0][1][z] = block[1][0][z];
    }
    return ret;
  }
  int Encode() {
    int ret = 0;
    REP(x, 3) REP(y, 3) REP(z, 3) {
      if (block[x][y][z]) {
        ret |= 1 << (z * 9 + y * 3 + x);
      }
    }
    return ret;
  }
  bool Move(int dir, int dist) {
    Block ret = *this;
    MEMSET(ret.block, 0);
    REP(x, 3) REP(y, 3) REP(z, 3) {
      if (block[x][y][z]) {
        int nx = x + dx[dir] * dist;
        int ny = y + dy[dir] * dist;
        int nz = z + dz[dir] * dist;
        if (nx < 0 || nx >= 3 || ny < 0 || ny >= 3 || nz < 0 || nz >= 3) { return false; }
        ret.block[nx][ny][nz] = true;
      }
    }
    *this = ret;
    return true;
  }
  bool operator<(const Block &rhs) const {
    return size < rhs.size;
  }
};

int StateRotateX(int enc) {
  int ret = enc & ((1 << 12) | (1 << 13) | (1 << 14));
  REP(x, 3) {
    ret |= ((enc >> (9 * 0 + 3 * 2 + x)) & 1) << (9 * 0 + 3 * 0 + x);
    ret |= ((enc >> (9 * 2 + 3 * 2 + x)) & 1) << (9 * 0 + 3 * 2 + x);
    ret |= ((enc >> (9 * 2 + 3 * 0 + x)) & 1) << (9 * 2 + 3 * 2 + x);
    ret |= ((enc >> (9 * 0 + 3 * 0 + x)) & 1) << (9 * 2 + 3 * 0 + x);
    ret |= ((enc >> (9 * 1 + 3 * 2 + x)) & 1) << (9 * 0 + 3 * 1 + x);
    ret |= ((enc >> (9 * 2 + 3 * 1 + x)) & 1) << (9 * 1 + 3 * 2 + x);
    ret |= ((enc >> (9 * 1 + 3 * 0 + x)) & 1) << (9 * 2 + 3 * 1 + x);
    ret |= ((enc >> (9 * 0 + 3 * 1 + x)) & 1) << (9 * 1 + 3 * 0 + x);
  }
  return ret;
}
int StateRotateY(int enc) {
  int ret = enc & ((1 << 10) | (1 << 13) | (1 << 16));
  REP(y, 3) {
    ret |= ((enc >> (9 * 0 + 3 * y + 2)) & 1) << (9 * 0 + 3 * y + 0);
    ret |= ((enc >> (9 * 2 + 3 * y + 2)) & 1) << (9 * 0 + 3 * y + 2);
    ret |= ((enc >> (9 * 2 + 3 * y + 0)) & 1) << (9 * 2 + 3 * y + 2);
    ret |= ((enc >> (9 * 0 + 3 * y + 0)) & 1) << (9 * 2 + 3 * y + 0);
    ret |= ((enc >> (9 * 1 + 3 * y + 2)) & 1) << (9 * 0 + 3 * y + 1);
    ret |= ((enc >> (9 * 2 + 3 * y + 1)) & 1) << (9 * 1 + 3 * y + 2);
    ret |= ((enc >> (9 * 1 + 3 * y + 0)) & 1) << (9 * 2 + 3 * y + 1);
    ret |= ((enc >> (9 * 0 + 3 * y + 1)) & 1) << (9 * 1 + 3 * y + 0);
  }
  return ret;
}
int StateRotateZ(int enc) {
  int ret = enc & ((1 << 4) | (1 << 13) | (1 << 22));
  REP(z, 3) {
    ret |= ((enc >> (9 * z + 3 * 0 + 2)) & 1) << (9 * z + 3 * 0 + 0);
    ret |= ((enc >> (9 * z + 3 * 2 + 2)) & 1) << (9 * z + 3 * 0 + 2);
    ret |= ((enc >> (9 * z + 3 * 2 + 0)) & 1) << (9 * z + 3 * 2 + 2);
    ret |= ((enc >> (9 * z + 3 * 0 + 0)) & 1) << (9 * z + 3 * 2 + 0);
    ret |= ((enc >> (9 * z + 3 * 1 + 2)) & 1) << (9 * z + 3 * 0 + 1);
    ret |= ((enc >> (9 * z + 3 * 2 + 1)) & 1) << (9 * z + 3 * 1 + 2);
    ret |= ((enc >> (9 * z + 3 * 1 + 0)) & 1) << (9 * z + 3 * 2 + 1);
    ret |= ((enc >> (9 * z + 3 * 0 + 1)) & 1) << (9 * z + 3 * 1 + 0);
  }
  return ret;
}

Block Decode(int enc) {
  Block ret;
  REP(z, 3) REP(y, 3) REP(x, 3) {
    if (enc & (1 << (z * 9 + y * 3 + x))) {
      ret.block[x][y][z] = true;
      ret.size++;
    }
  }
  return ret;
}

int Normalize(int enc) {
  int ret = 1 << 30;
  REP(i, 6) {
    if (i & 1) {
      enc = StateRotateX(enc);
    } else {
      enc = StateRotateY(enc);
    }
    REP(z, 4) {
      enc = StateRotateZ(enc);
      if (enc < ret) {
        ret = enc;
      }
    }
  }
  return ret;
}

void printState(int state) {
  REP(z, 3) {
    REP(y, 3) {
      REP(x, 3) {
        if (state & (1 << (9 * z + 3 * y + x))) {
          putchar('*');
        } else {
          putchar('.');
        }
      }
      puts("");
    }
    puts("");
  }
}

int W, D, H, N;
set<int> visit;
set<int> blockState[27];
Block blocks[27];

int restCheck(int state) {
  Graph g(29);
  Block block = Decode(state);
  REP(x, 3) {
    REP(y, 3) {
      REP(z, 3) {
        if (block.block[x][y][z]) { continue; }
        int from = z * 9 + y * 3 + x;
        if (from % 2 == 0) {
          g[27].push_back(Edge(27, from, 1));
        } else {
          g[from].push_back(Edge(from, 28, 1));
          continue;
        }
        REP(dir, 6) {
          int nx = x + dx[dir];
          int ny = y + dy[dir];
          int nz = z + dz[dir];
          if (nx < 0 || nx >= 3 || ny < 0 || ny >= 3 || nz < 0 || nz >= 3) { continue; }
          if (block.block[nx][ny][nz]) { continue; }
          int to = nz * 9 + ny * 3 + nx;
          g[from].push_back(Edge(from, to, 1));
          g[to].push_back(Edge(to, from, 0));
        }
      }
    }
  }
  return MaxFlow(g, 27, 28);
}

bool calc(int depth, int state) {
  if (depth == N) { return true; }
  state = Normalize(state);
  if (visit.count(state)) { return false; }
  visit.insert(state);
  if (blocks[depth].size == 2) {
    return restCheck(state) >= N - depth;
  }
  FORIT(it, blockState[depth]) {
    if (state & *it) { continue; }
    if (calc(depth + 1, state | *it)) { return true; }
  }
  return false;
}

int main() {
  while (scanf("%d %d %d %d", &W, &D, &H, &N), W|D|H|N) {
    visit.clear();
    REP(i, 27) { blockState[i].clear(); }
    int iniState = 0;
    REP(x, 3) REP(y, 3) REP(z, 3) {
      if (x >= W || y >= D || z >= H) {
        iniState |= 1 << (9 * z + 3 * y + x);
      }
    }
    int m = 0;
    REP(i, N) {
      int w, d, h;
      scanf("%d %d %d", &w, &d, &h);
      blocks[m] = Block();
      REP(z, h) {
        REP(y, d) {
          REP(x, w) {
            char c;
            scanf(" %c ", &c);
            if (c == '*') {
              blocks[m].block[x][y][z] = true;
              blocks[m].size++;
            }
          }
        }
      }
      if (blocks[m].size > 1) { m++; }
    }
    N = m;
    sort(blocks, blocks + N);
    reverse(blocks, blocks + N);
    REP(i, N) {
      REP(j, 6) {
        if (j & 1) {
          blocks[i] = blocks[i].RotateX();
        } else {
          blocks[i] = blocks[i].RotateY();
        }
        REP(z, 4) {
          blocks[i] = blocks[i].RotateZ();
          FOREQ(dist1, -2, 2) {
            FOREQ(dist2, -2, 2) {
              FOREQ(dist3, -2, 2) {
                Block b = blocks[i];
                if (b.Move(0, dist1) &&
                    b.Move(2, dist2) &&
                    b.Move(4, dist3)) {
                  int enc = b.Encode();
                  blockState[i].insert(enc);
                }
              }
            }
          }
        }
      }
    }
    if (calc(0, iniState)) {
      puts("Yes");
    } else {
      puts("No");
    }
  }
}
accuracy: 1
time_ms: 2830
memory_kb: 2692
final_rank: 2