xmu 1017

Description

    TheBeet有一个块大小为(2N*2N)的棋盘。这个棋盘是由一个个格子组成的。很不幸的,在一个月黑风高的晚上,它被摔坏了。不幸中的万幸,它只被摔坏了一个格子(此格子可以在棋盘的任意位置)。

但是这个棋盘再也不能用来下棋了,于是TheBeet想把这个棋盘切成如以下的几种小块。但是TheBeet不想浪费任何一个格子,您能帮助TheBeet么?

 

Input

每个输入文件只包含一组数据。

每组测试数据包含两行,第一行为N ( 1 <= N <= 10),表示棋盘的大小为2N。接下来那行里面有两个数字x, y(1 <= x, y <= 2N)表示这个残缺的格子在棋盘的第x行和第y列。

 

Output

如果不存在这样的划分情况,您的程序只需要输出"-1"(不包含引号)。否则输出整个棋盘的划分情况,每个相连的块用一个正整数字(范围[1, (2N*2N-1) / 3])来表示,原先的空洞地方请输出0。如果有多个划分情况满足题目要求,那么您只需要输出其中的一个。

 

Sample Input

2

2 3

 

Sample Output

2 2 3 3

2 1 0 3

4 1 1 5

4 4 5 5

 

Hint

This is a SPJ.

 

Source
xmu

 

首先这个不存在输出-1的情况。对于2*2的棋盘显然成立,对于4*4的棋盘我们可以平均分成四部分,必有一个部分包含坏掉的块,那么那一块已经满足条件了

剩下的3部分每个包含4块不符合条件,但是你会发现他们在分割线的中点处每个部分拿出一块来,这3块正好组成了一个题目要求的形状,而剩下的正好是满足条件的也就是和

包含坏掉块的那部分相同的情况,这就告诉我们可以用递归的方法来解决问题。我们已经知道缺一块的4*4方格可以满足条件,那么对于8*8呢只要在平均分4部分,对于包含坏

块的那部分由上面可知满足条件,而其他3部分只要把相交的中心部分各拿一块余下的部分也满足条件。到此我们就可以写代码了

#include<stdio.h>
int d[1111][1111];
int num=1;

void chess(int st , int en , int x , int y , int size)
{
	if(size<=1)
		return;
	int s=size>>1;
	int t=num++;
	if(x<s+st&&y<s+en) //左上方;
		chess(st,en,x,y,s);
	else
	{
		d[s+st-1][s+en-1]=t;
		chess(st,en,s+st-1,s+en-1,s);
	}
	if(x>=s+st&&y<s+en) //右上方;
		chess(s+st, en,x,y,s);
	else
	{
		d[s+st][s+en-1]=t;
		chess(s+st,en,s+st,en+s-1,s);
	}
	if(x<s+st&&y>=s+en) //左下方;
		chess(st,s+en,x,y,s);
	else
	{
		d[s+st-1][s+en]=t;
		chess(st,s+en,s+st-1,s+en,s);
	}
	if(x>=s+st&&y>=s+en) //右下方;
		chess(s+st,s+en,x,y,s);
	else
	{
		d[s+st][s+en]=t;
		chess(s+st,s+en,s+st,s+en,s);
	}
}

int main()
{
	int n , a1 ,a2,p,i;
	scanf("%d%d%d",&n,&a1,&a2);
	for(i=0,p=1;i<n;i++)
		p*=2;
	chess(1,1,a1,a2,p);
	for(a1=1;a1<=p;a1++)
	{
		for(a2=1;a2<p;a2++)
		{
			printf("%d ",d[a1][a2]);
		}
		printf("%d\n",d[a1][a2]);
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值