棋盘覆盖问题

问题:
在一个2k×2k个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。易知,覆盖任意一个2k×2k的特殊棋盘,用到的骨牌数恰好为(4K-1)/3。

输入格式
第一行为k(棋盘的尺寸),第二行为x,y(1<=x,y<=2^k),分别表示特殊方格所在行与列。

输出格式
共2^k行,分别表示覆盖该格的L型的编号(特殊格用0表示)。

测试输入:
3 3 2
预期输出:
3 3 4 4 8 8 9 9
3 2 2 4 8 7 7 9
5 2 6 6 10 10 7 11
5 5 0 6 1 10 11 11
13 13 14 1 1 18 19 19
13 12 14 14 18 18 17 19
15 12 12 16 20 17 17 21
15 15 16 16 20 20 21 21
提示:
特殊骨牌的牌号为0
正常骨牌号从1开始

在看到这个题的时候,如果还没有理解到题意的人会觉得这道题很难,原因就是在与不知道题目在说什么,但是当我们仔细读题的时候我们会发现,其实逻辑还是比较简单的。如果学过递归分治的同学就会很快知道怎么做。没错,我们这个题目就是使用这个思想:因为要把所有的位置都覆盖,所以其中的每一个“子集”也都会覆盖,我们不妨把棋盘以“田”字的形式均等分开,当我们再看每一部分的时候,我们就会遇见与之前一样的问题,这就是“递归分治”思想,“分而治之”,将每个小问题以“原子”的形式解决,最后将全部的子问题解决了就是整个问题的解。

因为放置骨牌的顺序不同,所以这个题答案有多个,要根据题目要求,写不同的代码逻辑,当然也只是交换一下语句的位置,并没有实质性的不同,接下来就看看这个代码:

#include<stdio.h>
#include<math.h>
int Board[100][100];//棋盘大小 
int title=1;//骨牌 

void ChessBoard(int tr,int tc,int dr,int dc,int size){
	if(size == 1){
		return ;
	}
	int s = size/2;
	int t = title++;
	if(tr+s>dr&&tc+s>dc){//当特殊方格在第一象限 
		ChessBoard(tr,tc,dr,dc,s);
	}else{
		Board[tr+s-1][tc+s-1] = t;
		ChessBoard(tr,tc,tr+s-1,tc+s-1,s);
	}
	
	if(tr+s>dr&&tc+s<=dc){//当特殊方格在第二象限 
		ChessBoard(tr,tc+s,dr,dc,s);
	}else{
		Board[tr+s-1][tc+s] = t;
		ChessBoard(tr,tc+s,tr+s-1,tc+s,s);
	}
	
	if(tr+s<=dr&&tc+s>dc){//当特殊方格在第三象限 
		ChessBoard(tr+s,tc,dr,dc,s);
	}else{
		Board[tr+s][tc+s-1] = t;
		ChessBoard(tr+s,tc,tr+s,tc+s-1,s);
	}
	
	if(tr+s<=dr&&tc+s<=dc){//当特殊方格在第四象限 
		ChessBoard(tr+s,tc+s,dr,dc,s);
	}else{
		Board[tr+s][tc+s] = t;
		ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
	}
} 


int main(){
	int size;
	int dr,dc;
	scanf("%d %d %d",&size,&dr,&dc);
	size = pow(2,size);
	ChessBoard(0,0,dr,dc,size);
	for(int i=0;i<size;i++){
		for(int j=0;j<size-1;j++){
			printf("%-4d",Board[i][j]);
		}
        printf("%d",Board[i][size-1]);
		printf("\n");
	}
}

代码看起来挺多,是因为有四个if-else,只要把其中一个看懂了其他的就都好了,其中最重要的就是不要把判断语句的边界写错了。
当然这只是我个人的做法,还有其他的欢迎留言


------------------------------------------------------------------------风里雨里,之都等你


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值