1055 - Pockets

Origami, or the art of paper folding, often makes use of ``pockets" of paper, particularly in complicated models made from multiple pieces of paper where a tab on one piece of paper needs to fit into a pocket in another piece of paper. In this problem you must count pockets in a flat folded square of paper. A pocket is defined as any opening (lying between two surfaces of paper) that is accessible from the boundary of the folded piece of paper. Note that one accessible opening can account for several pockets since each open side contributes one pocket. Figure 1 shows an example. Observe that the ``middle" opening (between the second and third layers of paper) contributes 3 to the total pocket count.

\epsfbox{p3568a.eps}

Figure 1: Pockets

Assume the paper is initially lying on a flat surface and is never completely lifted from the surface. All folds will be horizontal or vertical. Fold lines will fall only along equally-spaced crease lines, N in each direction. On the original unfolded square, creases and edges are numbered from top to bottom and from left to right as shown in Figure 2. Each fold reduces the boundary of the folded piece of paper to a smaller rectangle; the final fold results in a square one unit in each direction. Folds are described using a crease line and a direction. For instance, `2 U' means to fold the bottom edge up using horizontal crease 2; `1 L' means to fold the right edge to the left using crease 1. (See Figure 2.) After several folds, creases may be aligned (for instance, creases 1 and 3 in Figure 2). Either number may be used to specify a fold along that line (so, in Figure 2, `1 D' and `3 D' are equivalent instructions after the first fold). Pockets are to be counted for the boundary of the final one-unit square. Once a crease is made it cannot be undone. All creases go through every layer of paper from top to bottom; disregard paper thickness.

\epsfbox{p3568b.eps}

Input 

Input is a sequence of test cases. Each test case begins with a line containing two integers, N and KN is the number of horizontal crease lines (the same as the number of vertical crease lines) of the square. Creases are numbered 1, 2,..., N from top to bottom and from left to right. K is the number of folds to be made. N and K are each less than or equal to 64.

Following N and K are K fold descriptions. Each fold description consists of an integer crease number C and a direction, either UDL, or R (for up, down, left or right) separated by whitespace. Whitespace also precedes and follows each fold description.

The final result for each test case will be a square one unit in size.

The final test case is followed by a line containing two zeroes.

Output 

For each input case, display the case number followed by the number of pockets in the final one-unit square. Use the format shown in the sample output.

Sample Input 

1 2 
1 R 1 U 
3 5 
2 U 1 L 
  3   D 
3 R 2 L 
0 0

Sample Output 

Case 1: 7 pockets 
Case 2: 17 pockets

Claimer: The data used in this problem is unofficial data prepared by Derek Kisman. So any mistake here does not imply mistake in the offcial judge data. Only Derek Kisman is responsible for the mistakes. Report mistakes to dkisman@acm.org








#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct info
{
	int sign;
	int up,down,uCover,dCover;
	int sum;
};
const int MaxN=64;
int Cases,N,n,m,K,ans;
char dir;
info hor[MaxN+2][MaxN+1],ver[MaxN+1][MaxN+2];
info Nhor[MaxN+2][MaxN+1],Nver[MaxN+1][MaxN+2];
int Lhor[MaxN+1],Lver[MaxN+1];

void init()
{
	int i;
	memset(hor,0,sizeof(hor));
	memset(ver,0,sizeof(ver));
	for(i=0;i<n;i++)
	{
		hor[0][i].sign=hor[n][i].sign=1;
		hor[0][i].sum=hor[n][i].sum=1;
		ver[i][0].sign=ver[i][n].sign=1;
		ver[i][0].sum=ver[i][n].sum=1;
	}
	for(i=0;i<=n;i++)
		Lhor[i]=Lver[i]=i;
}

int get(int x,int s,int line,char dir)
{
	if(dir=='D' || dir=='R')
		return labs(x-line);
	else if(line+line>=s)
	{
		if(x<=line)
			return x;
		return line-(x-line);
	}
	else
	{
		if(x>=line)
			return s-x;
		return (s-line)-line+x;
	}
}

void work()
{
	int i,j,k,nNew,mNew,x,y;
	int line;
	char dir;
	scanf("%d%c",&line,&dir);
	while(dir!='U' && dir!='D' && dir!='R' && dir!='L')
		scanf("%c",&dir);
	if(dir=='U' || dir=='D')
	{
		line=Lhor[line];
		mNew=m;
		if(line>n-line)
			nNew=line;
		else
			nNew=n-line;
		for(i=0;i<=N;i++)
			Lhor[i]=get(Lhor[i],n,line,dir);
	}
	else
	{
		line=Lver[line];
		nNew=n;
		if(line>m-line)
			mNew=line;
		else
			mNew=m-line;
		for(i=0;i<=N;i++)
			Lver[i]=get(Lver[i],m,line,dir);
	}
	memset(Nhor,0,sizeof(Nhor));
	memset(Nver,0,sizeof(Nver));
	for(i=0;i<nNew;i++)
		Nver[i][0].sign=Nver[i][mNew].sign=1;
	for(i=0;i<mNew;i++)
		Nhor[0][i].sign=Nhor[nNew][i].sign=1;
	if(dir=='U')
		for(i=0;i<mNew;i++)
			Nhor[nNew][i].sum=1;
	if(dir=='D')
		for(i=0;i<mNew;i++)
			Nhor[0][i].sum=1;
	if(dir=='L')
		for(i=0;i<nNew;i++)
			Nver[i][mNew].sum=1;
	if(dir=='R')
		for(i=0;i<nNew;i++)
			Nver[i][0].sum=1;
	for(i=0;i<=n;i++)
		for(j=0;j<m;j++)
		{
			x=i;y=j;
			if(dir=='U' || dir=='D')
				x=get(x,n,line,dir);
			else
				y=get(y,m,line,dir);
			if((dir=='R' && j<line) || (dir=='L' && j>=line))
				y--;
			if(Nhor[x][y].sign)
			{
				if(hor[i][j].sign)
					Nhor[x][y].sum+=hor[i][j].sum;
				else
					Nhor[x][y].sum +=hor[i][j].down;
			}
			else
			{
				if(hor[i][j].sign)
				{
					if((i<line&&dir=='U') || (i>=line && dir=='D'))
						Nhor[x][y].down+=hor[i][j].sum;
					else
						Nhor[x][y].up+=hor[i][j].sum;
				}
				else
				{
					if((i<line&&dir=='U') || (i>=line&&dir=='D') || (j<line&&dir=='L') || (j>=line&&dir=='R'))
					{
						Nhor[x][y].down=hor[i][j].down;
						Nhor[x][y].dCover=1;
						if(!Nhor[x][y].uCover)
							Nhor[x][y].up+=hor[i][j].up;
					}
					else
					{
						Nhor[x][y].up=hor[i][j].down;
						Nhor[x][y].uCover=1;
						if(!Nhor[x][y].dCover)
							Nhor[x][y].down+=hor[i][j].up;
					}
				}
			}
		}
	for(i=0;i<n;i++)
		for(j=0;j<=m;j++)
		{
			x=i;
			y=j;
			if(dir=='U' || dir=='D')
				x=get(x,n,line,dir);
			else
				y=get(y,m,line,dir);
			if((dir=='U' && i>=line) || (dir=='D'&&i<line))
				x--;
			if(Nver[x][y].sign)
			{
				if(ver[i][j].sign)
					Nver[x][y].sum+=ver[i][j].sum;
				else
					Nver[x][y].sum+=ver[i][j].down;
			}
			else
			{
				if(ver[i][j].sign)
				{
					if((j<line&&dir=='L')||(j>=line&&dir=='R'))
						Nver[x][y].down+=ver[i][j].sum;
					else
						Nver[x][y].up+=ver[i][j].sum;
				}
				else
				{
					if((i<line&&dir=='U')||(i>=line&&dir=='D')||(j<line&&dir=='L')||(j>=line&&dir=='R'))
					{
						Nver[x][y].down=ver[i][j].down;
						Nver[x][y].dCover=1;
						if(!Nver[x][y].uCover)
							Nver[x][y].up+=ver[i][j].up;
					}
					else
					{
						Nver[x][y].up=ver[i][j].down;
						Nver[x][y].uCover=1;
						if(!Nver[x][y].dCover)
							Nver[x][y].down+=ver[i][j].up;
					}
				}
			}
		}
		memcpy(hor,Nhor,sizeof(hor));
		memcpy(ver,Nver,sizeof(ver));
		n=nNew;m=mNew;
}

int main()
{
	while(scanf("%d %d",&n,&K) && (n||K))
	{
		n++;
		N=m=n;
		init();
		for(;K;K--)
		work();
		ans=hor[0][0].sum-1+hor[1][0].sum-1+ver[0][0].sum-1+ver[0][1].sum-1;
		printf("Case %d: %d pockets\n",++Cases,ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值