棋盘覆盖问题(Tromino谜题)
棋盘覆盖问题程序说明

棋盘覆盖问题
对一M*N棋盘,假设有外形完全一样的骨排.每一骨排可覆盖棋盘上两相邻的方格.若用一些骨排覆盖棋盘,使棋盘上所有格被盖,且不交叉,称完全覆盖,.8*8棋盘是否可以完全覆盖?
编程思想:将棋盘设为一个M*N数组,对数组中每个元素分别赋值0和1,并使每个元素与其周围元素的值不相等。
再将数组中对角元素赋给0,1以外的值。
统计数组中0元素与1元素的个数。
若相等,证明可以完全覆盖,不相等则不能完全覆盖。
本程序特点:棋盘的行数和列数可以是任意的。
只需输入行数和列数便可得到结论。
缺点:棋盘只能是缺少对角的,不能是缺少任意的几格。
棋盘覆盖问题的求解

棋盘覆盖问题的求解棋盘覆盖问题是一个经典的数学问题,它引发了人们对于数学中的逻辑思维和问题解决能力的思考。
在这篇文章中,我将为大家详细介绍棋盘覆盖问题的求解方法,并希望能够帮助中学生和他们的父母更好地理解和应用这一问题。
棋盘覆盖问题是指如何用特殊形状的骨牌将一个2^n × 2^n的棋盘完全覆盖的问题。
其中,骨牌的形状分为4种,分别为L型、反L型、凸型和凹型。
在求解这个问题时,我们需要遵循以下几个步骤。
首先,我们需要将给定的棋盘划分为四个相等的小棋盘。
这样,我们就可以将问题分解为四个子问题,分别是将四个小棋盘覆盖完整。
接下来,我们就可以通过递归的方式来解决每个子问题。
在解决子问题时,我们需要根据骨牌的形状来选择放置的位置。
以L型骨牌为例,我们可以将其放置在左上角、左下角或者右上角。
通过不同的放置位置,我们可以将子问题进一步分解为更小的子问题。
同样地,我们可以使用相同的方法来解决反L型、凸型和凹型骨牌。
在每个子问题中,我们需要注意两个关键点。
首先,我们需要保证每个小棋盘上的骨牌能够完全覆盖。
这就要求我们在放置骨牌时,需要选择合适的位置和方向。
其次,我们需要保证四个小棋盘的边缘能够对齐。
这样,才能保证最终的结果是一个完整的棋盘。
通过不断地递归求解子问题,我们最终可以将整个棋盘完全覆盖。
这个过程中,我们需要注意边界条件的处理,以及递归函数的设计。
同时,我们还可以通过剪枝等优化方法来提高算法的效率。
棋盘覆盖问题的求解方法不仅仅是一个数学问题,更是一个思维训练的过程。
通过解决这个问题,我们可以培养自己的逻辑思维能力、问题解决能力和创新思维。
同时,这个问题也具有一定的实用性,可以用于解决一些实际问题,如图像处理、计算机视觉等领域。
总结一下,棋盘覆盖问题是一个经典的数学问题,通过将棋盘划分为四个小棋盘,我们可以通过递归的方式来解决每个子问题。
在解决子问题时,我们需要选择合适的骨牌形状和放置位置,同时保证边缘对齐和完全覆盖。
2020小学六年级奥数知识点:第十一讲 棋盘中的数学—棋盘覆盖的问题

解:图形(1)和(2)中各有11个方格,11不是3的倍数,因此不能用这两种图形拼成.
图形来拼.
只有图形(4)可以用这两种三个方格的图形来拼,具体拼法有多种,下图仅举出一种为例.
说明:排除图(1)与(2)的方法是很重要的.因为一个图形可以用这是“必要条件排除法”.但要注意,一个图形小方格数是3的倍数,也不表明的就是这种情况.
证明:用6种“方块”构成4×7棋盘已如上图所示.
下面我们证明不能用七种“方块”各一块构成4×7的长方形棋盘.
将长方形的28个小方格如右图黑、白相间进行染色,则黑、白格各为个白格1个黑格,而其余六种方块图形皆占据黑格、白格各2个.因此,7种方块图形占据的黑白格数必都是奇数,不会等于14.
这类问题,容易更加一般化,即用2×1的方格骨牌去覆盖一个m×n的方格棋盘的问题.
定理1: m×n棋盘能被2×1骨牌覆盖的充分且必要的条件是m、n中至少有一个是偶数.
证明:①充分性:即已知m,n中至少有一个偶数,求证:m×n棋盘可被2×1骨牌覆盖.不失一般性,设m=2k,则m×n=2k×n=k×
棋盘可被kn个2×1骨牌覆盖.
②必要性:即已知m×n棋盘可以被2×1骨牌覆盖.求证:m,n中至少有一个偶数.若m×n棋盘可被2×1骨牌覆盖,则必覆盖偶数个方格,即mn是个偶数,因此m、n中至少有一个是偶数.
例2 下图中的8×8棋盘被剪去左上角与右下角的两个小方格,问能否用31个2×1的骨牌将这个剪残了的棋盘盖住?
第二步:不用1×1而只用2×2与3×3的正方形是拼不成的.将23×23的大正方形的1,4,7,10,13,16,19,22各行染红色,其余各行染蓝色如下图.任意2×2或3×3正方形都将包含偶数个蓝色小格,但蓝格总数是23×15,是个奇数,矛盾.所以不用1×1的小正方形是拼不成23×23棋盘的.
棋盘覆盖问题算法思路

棋盘覆盖问题算法思路棋盘覆盖问题是一个经典的递归问题,其原始问题定义如下:给定一个2^n*2^n的棋盘,其中一个方格被标记,将该棋盘分割成4个2^(n-1)*2^(n-1)的小棋盘,同时以递归的方式,将标记方格分割到4个小棋盘之一,并覆盖其他方格。
重复此过程,直到达到基本情况,即当棋盘大小为2*2,无需分割。
我们可以使用分治法来解决这个问题,即将一个大问题分解为多个小问题,并最终将它们的解组合起来得到原问题的解。
下面是一个算法思路:1.定义一个棋盘的类,表示一个棋盘对象。
其中包括棋盘的大小、标记方格的位置坐标等信息。
2. 定义一个递归函数cover(board, size, tr, tc, dr, dc),其中board表示当前的棋盘对象,size表示当前棋盘的大小,(tr, tc)表示当前棋盘左上角方格的坐标,(dr, dc)表示标记方格的坐标。
3.首先检查当前棋盘大小是否为2*2,如果是,则直接将标记方格的位置填充到其他3个方格,并返回。
4. 否则,将当前棋盘的大小减半,计算出当前棋盘分割后4个小棋盘的左上角方格坐标和标记方格的位置坐标(nt, nl, nr, nc)。
5. 然后分别递归调用cover函数对4个小棋盘进行覆盖,需要注意传递的参数:a. 对于第一个小棋盘,其大小为size / 2,左上角坐标为(tr, tc),标记方格的坐标为(nt, nl)。
b. 对于第二个小棋盘,其大小为size / 2,左上角坐标为(tr, tc + size / 2),标记方格的坐标为(nr, nc)。
c. 对于第三个小棋盘,其大小为size / 2,左上角坐标为(tr + size / 2, tc),标记方格的坐标为(nr, nc)。
d. 对于第四个小棋盘,其大小为size / 2,左上角坐标为(tr + size / 2, tc + size / 2),标记方格的坐标为(nt, nl)。
6.最后,将4个小棋盘的覆盖结果组合起来得到原问题的解,并将该结果填充到当前棋盘。
棋盘覆盖算法

棋盘覆盖算法棋盘覆盖算法(Tiling Puzzle)是用小的拼图块填满一个大的棋盘的问题,这些拼图块称作多米诺骨牌,每一块都覆盖两个格子,而棋盘的大小为2的n次方×2的n次方,其中n是整数。
在一个棋盘和一组多米诺骨牌下,棋盘恰好可以被所有的多米诺骨牌覆盖,且每个多米诺骨牌恰好覆盖两个格子。
棋盘覆盖算法是一个NP难问题,它需要在指数时间内找到最佳解决方案。
但是,对于许多小规模的问题,我们可以使用回溯算法来得到最佳解决方案。
回溯算法是一种试探性算法,最初解答第一个问题,可进一步解答其他问题。
该算法探讨所有可能的解决方案,直到找到正确的方案。
如果没有正确的解决方案,那么回溯算法将返回到较早的步骤并尝试其他方案。
因此,我们可以使用回溯算法来解决这个问题。
当我们覆盖一个多米诺骨牌时,我们可以检查是否存在其他多米诺骨牌可以覆盖未覆盖的部分,并将这些多米诺骨牌添加到棋盘的布局中。
如果我们在棋盘上填好所有的多米诺骨牌,那么我们就找到了正确的解决方案。
步骤:1. 首先在棋盘上选择一个没有被覆盖的格子。
2. 从所有可以放置在这个格子上的多米诺骨牌中,选择一个多米诺骨牌放到这个位置上。
3. 如果这个多米诺骨牌可以被放置在棋盘上的其他未被覆盖的位置上,那么就在这个位置上放置。
4. 重复步骤2和3,一直到所有的多米诺骨牌都被放置在棋盘上。
5. 如果无法放置更多的多米诺骨牌了,那么我们就找到了一个正确的解决方案。
如果仍有多米诺骨牌没有被放置,那么我们就返回步骤2,并尝试用其他的多米诺骨牌进行覆盖。
6. 最终,我们找到的正确的解决方案就是把所有多米诺骨牌都放置在位置上的布局。
总之,棋盘覆盖算法是一个重要的问题,它在计算机科学领域中具有广泛的应用。
在实际应用中,我们可以使用计算机来解决这个问题,例如利用回溯算法。
小学六年级奥数★棋盘的覆盖

棋盘的覆盖同学们会下棋吗?下棋就要有棋盘,下面是中国象棋的棋盘(图1),围棋棋盘(图2)和国际象棋棋盘(图3)。
用某种形状的卡片,按一定要求将棋盘覆盖住,就是棋盘的覆盖问题。
例1要不重叠地刚好覆盖住一个正方形,最少要用多少个下图所示的图形?例2 能否用17个形如的卡片将下图刚好覆盖?例3 下图的七种图形都是由4个相同的小方格组成的。
现在要用这些图形拼成一个4×7的长方形(可以重复使用某些图形),那么,最多可以用上几种不同的图形?例4 用1×1,2×2,3×3的小正方形拼成一个11×11的大正方形,最少要用1×1的正方形多少个?例5用七个1×2的小长方形覆盖下图,共有多少种不同的覆盖方法?例6有许多边长为1厘米、2厘米、3厘米的正方形硬纸片。
用这些硬纸片拼成一个长5厘米、宽3厘米的长方形的纸板,共有多少种不同的拼法?(通过旋转及翻转能相互得到的拼法认为是相同的拼法)课后练习1.在4×4的正方形中,至少要放多少个形如所示的卡片,才能使得在不重叠的情形下,不能再在正方形中多放一个这样的卡片?(要求卡片的边缘与格线重合)2.下列各图中哪几个能用若干个或拼成?3.能否用9个形如的卡片覆盖住6×6的棋盘?4.小明有8张连在一起的电影票(如右图),他自己要留下4张连在一起的票,其余的送给别人。
他留下的四张票可以有多少种不同情况?5.有若干个边长为1、边长为2、边长为3的小正方形,从中选出一些拼成一个边长为4的大正方形,共有多少种不同拼法?(只要选择的各种小正方形的数目相同就算相同的拼法)6.用6个形如的卡片覆盖下图,共有多少种不同的覆盖方法?7.能不能用9个1×4的长方形卡片拼成一个6×6的正方形?答案与提示练习151.3个。
提示:左下图是一种放法。
2.图(2)。
提示:图(1)的小方格数不是3的倍数;图(3)的小方格数是3的倍数但拼不成;图(2)的拼法见右上图。
棋盘覆盖问题
棋盘覆盖问题1.实验题目要求用4种不同形状的L型骨牌(分别为L旋转90度、180度、270度、360度所成图形,且每个图形均只含有三个小方格)覆盖给定棋盘上出特殊方格以外的所有方格,且任何两个L型骨牌不得重叠覆盖。
2.实验目的(1)进一步掌握递归算法的设计思想以及递归程序的调试技术;(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。
3.实验要求(1)用分治法解决棋盘覆盖问题;(2)分析算法的时间性能。
4.程序实现#include<stdio.h>#define N 4int board[N][N]={0};void ChessBoard(int tr,int tc,int dr,int dc,int size){int s;if(size==1) return;static int c=1;int t=c++;s=size/2;if(dr<tr+s&&dc<tc+s)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(dr<tr+s&&dc>=tc+s)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(dr>=tr+s&&dc<tc+s)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(dr>=tr+s&&dc>=tc+s)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);}}void main(){int i,j;int a[N][N]={0};for(i=0;i<=N-1;i++){for(j=0;j<=N-1;j++){printf("%5d",a[i][j]);}printf("\n");}int tr=0,tc=0,dr,dc;printf("请在以上的棋盘中选择特殊方格的位置并输入其坐标(坐标计数从0开始):\n"); scanf("%d%d",&dr,&dc);ChessBoard(tr,tc,dr,dc,N);for(i=0;i<=N-1;i++){for(j=0;j<=N-1;j++){printf("%5d",board[i][j]);}printf("\n");}}5.时间复杂性分析设T(k)是覆盖一个2k×2k棋盘所需时间,从算法的划分策略可知,T(k)满足以下递推式:k=0时,T(k)=O(1);k>0时,T(k)=4T(k-1)+O(1);就此递推式可得T(k)=O(4k)。
棋盘覆盖问题的算法实现(代码及截图)
if(dr>=tr+s &&dc<tc+s) 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(dr>=tr+s &&dc>=tc+s) 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); } } void main() { int i,j,k,a,b; printf("请输入特殊方格的坐标:"); scanf("%d %d",&a,&b); ChessBoard(0,0,a,b,4); for(k=0;k<tile;k++) { printf("编号为%d的型骨牌的坐标为:",k); for(i=0;i<4;i++) for(j=0;j<4;j++) { if(Board[i][j]==k&&(i!=a||j!=b)) printf("(%d,%d)",i,j); } printf("\n"); } }
棋盘覆盖问题的算法实现
在一个2^k * 2^k个方格组成的棋盘中,有一个方格与其它的 不同,若使用以下四种L型骨牌覆盖除这个特殊方格的其它方 格,如何覆盖。 四个L型骨牌如下图1
趣题:免分割线的多米诺骨牌覆盖方案
问题:能否用多米诺骨牌既无重复又无遗漏地覆盖一个6 × 6 的棋盘,使得棋盘上的每一条水平线和每一条竖直线都会穿过至少一个多米诺骨牌?举个例子,下图所示的棋盘覆盖方案就是不满足要求的,因为棋盘的第二条水平线不会切断任何一个多米诺骨牌。
满足要求的棋盘覆盖是不存在的。
我们有一个非常漂亮的证明。
注意到,任意一条水平线都会把整个棋盘分成上下两部分,这两部分所包含的小正方形的个数都是偶数。
那些完全在这条线上面的多米诺骨牌会占据其中偶数个格子,那些完全在这条线下面的多米诺骨牌也会占据其中偶数个格子,因而棋盘的上下两部分各剩下了偶数个格子,这些格子就留给了那些穿过了这条水平线的多米诺骨牌来占据。
每一个穿过了这条线的多米诺骨牌都会在上下两部分棋盘各占据一个格子,因此为了完全覆盖棋盘,这样的多米诺骨牌必须得有偶数个才行。
结论就是:在一个满足要求的棋盘覆盖方案中,每条水平线都会穿过至少两个多米诺骨牌。
同理,每条竖直线也都会穿过至少两个多米诺骨牌。
然而,在 6 × 6 的棋盘中,水平线和竖直线一共有10 条,每条线上都有两个多米诺骨牌,这显然是不现实的,因为整个棋盘里一共也只能放下18 个多米诺骨牌。
有趣的是,棋盘再稍微大一些,这种推理就失效了。
在一个8 × 8 的棋盘中,水平线和竖直线一共有14 条,它们对应于28 个多米诺骨牌,这却并不会导致矛盾,因为棋盘里一共能放下32 个多米诺骨牌。
那么,8 × 8 的棋盘是否存在满足要求的覆盖方案呢?更一般地,对于哪些正整数M 和N ,在一个M × N 的棋盘里存在满足要求的覆盖方案呢?注意,M 和N 这两个数当中至少得有一个数是偶数,否则整个棋盘将会有奇数个小方格,这根本不可能被多米诺骨牌既无重复又无遗漏地覆盖住。
不妨假设M ≤ N 。
M = 1 和M = 2 的情况基本上可以直接被排除了(不过,这里面有一个特例,即(M, N) = (1, 2) 可以算作是一个平凡解)。
棋盘覆盖问题
ChessBoard(tr, tc+s, tr+s-1, tc+s, s); } // 覆盖左下角子棋盘 if (dr >= tr + s && dc < tc + s) // 特殊方格在左下角子棋盘中
ChessBoard(tr+s, tc, dr, dc, s); //递归处理子棋盘 else { // 用 t 号L型骨牌覆盖右上角,再递归处理子棋盘
棋盘覆盖问题要求用如图(b)所示的L型骨 牌覆盖给定棋盘上除特殊方格以外的所有方格, 且骨牌之间不得有重叠。
(a) k=2时的一种棋盘
(b) 4种不同形状的L型骨牌
棋盘覆盖问题
残缺棋盘是一个有2k×2k (k≥1)个方格的棋盘,其中恰有 一个方格残缺。图4-7给出k=1时各种可能的残缺棋盘,其 中残缺的方格用阴影表示。
board[tr + s][tc + s] = t;
ChessBoard(tr+s, tc+s, tr+s, tc+s, s); }
}
#include <stdio.h>
#define N 16
int a[100][100];
int t=1;
void Tromino(int (*a)[N],int dr,int dc,int tr,int tc,int size)
图 一个4*4的残缺棋盘
从以上例子还可以发现,当残缺方格在第1个子棋盘,用① 号三格板覆盖其余三个子棋盘的交界方格,可以使另外三 个子棋盘转化为独立子问题;同样地(如下图所示),当 残缺方格在第2个子棋盘时,则首先用②号三格板进行棋盘 覆盖,当残缺方格在第3个子棋盘时,则首先用③号三格板 进行棋盘覆盖,当残缺方格在第4个子棋盘时,则首先用④ 号三格板进行棋盘覆盖,这样就使另外三个子棋盘转化为 独立子问题。如下图:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
tc
tr
dc
dr
size
棋盘覆盖问题中的数据结构
算法——棋盘覆盖
void ChessBoard(int tr, int tc, int dr, int dc, int size)
// tr和tc是棋盘左上角的下标,dr和dc是特殊方格的下标,
// size是棋盘的大小,t已初始化为0
{
if (size = = 1) return; //棋盘只有一个方格且是特殊方格
{
int s;
if(size==1) return;
if(size>1)
{
s=size/2;
if(dr<=(tr+s-1)&&dc<=(tc+s-1))
/*特殊方块在左上部分
*/
{
a[tr+s-1][tc+s]=t;
a[tr+s][tc+s]=t;
a[tr+s][tc+s-1]=t;
t++;
Tromino(a,dr,dc,tr,tc,s);
board[tr + s - 1][tc + s - 1] = t;
ChessBoΒιβλιοθήκη rd(tr, tc, tr+s-1, tc+s-1, s);
}
// 覆盖右上角子棋盘
if (dr < tr + s && dc >= tc + s) // 特殊方格在右上角子棋盘中
ChessBoard(tr, tc+s, dr, dc, s);
for(j=0;j<N;j++) printf("%-4d",a[i][j]);
printf("\n"); } system("pause"); }
设T(k)是覆盖一个2k×2k棋盘所需时间,从 算法的划分策略可知,T(k)满足如下递推式:
O(1)
k 0
T (k) 4T (k 1) O(1) k 0
Tromino(a,tr+s-1,tc+s,tr,tc+s,s);
Tromino(a,tr+s,tc+s,tr+s,tc+s,s);
Tromino(a,tr+s,tc+s-1,tr+s,tc,s);
if(dr<=(tr+s-1)&&dc>(tc+s-1))
/*特殊方块在右上部分*/
{
a[tr+s-1][tc+s-1]=t;
ChessBoard(tr+s, tc, dr, dc, s); //递归处理子棋盘
else { // 用 t 号L型骨牌覆盖右上角,再递归处理子棋盘
board[tr + s][tc + s - 1] = t;
ChessBoard(tr+s, tc, tr+s, tc+s-1, s); }
// 覆盖右下角子棋盘
2k-1×2k-1 2k-1×2k-1
2k-1×2k-1 2k-1×2k-1
(a)棋盘分割
(b) 构造相同子问题
下面介绍棋盘覆盖问题中数据结构的设计: (1)棋盘:用二维数组board[size][size]表示一 个棋盘,其中,size=2k。为了在递归处理的过程 中使用同一个棋盘,将数组board设为全局变量;
解此递推式可得T(k)=O(4k)。
}
if(dr>(tr+s-1)&&dc<=(tc+s-1)) /*特殊方块在左下部分*/
{
a[tr+s-1][tc+s-1]=t;
a[tr+s-1][tc+s]=t;
a[tr+s][tc+s]=t;
t++;
Tromino(a,dr,dc,tr+s,tc,s);
Tromino(a,tr+s-1,tc+s-1,tr,tc,s);
ChessBoard(tr+s, tc+s, tr+s, tc+s, s); }
}
问题描述:在一个2^k×2^k 个方格组成的棋盘中,恰有一 个方格与其它方格不同,称该方格为一特殊方格,且称该 棋盘为一特殊棋盘。在棋盘覆盖问题中,要用4种不同形态 的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方 格,且任何2个L型骨牌不得重叠覆盖。 算法思想: 用分治策略,可以设计出解棋盘覆盖问题的简洁算法。 (1)当k>0时,将2的k次幂乘以2的k次幂棋盘分割为4个2的 k-1次幂乘以2的k-1次幂子棋盘。 (2)特殊方格必位于4个较小棋盘之一中,其余3个子棋盘中 无特殊方格。 (3)为了将这3个无特殊方格的子棋盘转化为特殊棋盘,可 以用一个L型骨牌覆盖这3个较小棋盘的会合处,这3个子棋 盘上被L型骨牌覆盖的方格就成为该棋盘上的特殊方格,从 而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使 用这种分割,直至棋盘简化为1*1棋盘。
if (dr >= tr + s && dc >= tc + s) // 特殊方格在右下角子棋盘中
ChessBoard(tr+s, tc+s, dr, dc, s); //递归处理子棋盘
else { // 用 t 号L型骨牌覆盖左上角,再递归处理子棋盘
board[tr + s][tc + s] = t;
t++; // L型骨牌号
s = size/2; // 划分棋盘
// 覆盖左上角子棋盘
if (dr < tr + s && dc < tc + s) // 特殊方格在左上角子棋盘中
ChessBoard(tr, tc, dr, dc, s);
//递归处理子棋盘
else{ // 用 t 号L型骨牌覆盖右下角,再递归处理子棋盘
//递归处理子棋盘
else { // 用 t 号L型骨牌覆盖左下角,再递归处理子棋盘
board[tr + s - 1][tc + s] = t;
ChessBoard(tr, tc+s, tr+s-1, tc+s, s); }
// 覆盖左下角子棋盘
if (dr >= tr + s && dc < tc + s) // 特殊方格在左下角子棋盘中
tr:棋盘左上角方格的行号 tc:棋盘左上角方格的列号 dr:特殊方格所在的行号 dc:特殊方格所在的列号 size:方形棋盘的边长
#include <stdio.h>
#define N 16
int a[100][100];
int t=1;
void Tromino(int (*a)[N],int dr,int dc,int tr,int tc,int size)
a[tr+s][tc+s-1]=t;
a[tr+s][tc+s]=t;
t++;
Tromino(a,dr,dc,tr,tc+s,s);
Tromino(a,tr+s-1,tc+s-1,tr,tc,s);
Tromino(a,tr+s,tc+s-1,tr+s,tc,s);
Tromino(a,tr+s,tc+s,tr+s,tc+s,s);
棋盘覆盖问题
在一个2k×2k (k≥0)个方格组成的棋盘中, 恰有一个方格与其他方格不同,称该方格为特殊 方格。
棋盘覆盖问题要求用如图(b)所示的L型骨牌 覆盖给定棋盘上除特殊方格以外的所有方格,且 骨牌之间不得有重叠。
(a) k=2时的一种棋盘
(b) 4种不同形状的L型骨牌
分治策略
• 技巧在于划分棋盘,使每个子棋盘均包含一 个特殊方格,从而将原问题分解为规模较小的 棋盘覆盖问题
(2)子棋盘:在棋盘数组board[size][size]中, 由子棋盘左上角的下标tr、tc和棋盘边长s表示;
(3)特殊方格:用board[dr][dc]表示,dr和dc是 该特殊方格在棋盘数组board中的下标;
(4) L型骨牌:一个2k×2k的棋盘中有一个特殊 方格,所以,用到L型骨牌的个数为(4k-1)/3,将所 有L型骨牌从1开始连续编号,用一个全局变量t表 示
t++;
Tromino(a,dr,dc,tr+s,tc+s,s);
Tromino(a,tr+s,tc+s-1,tr+s,tc,s);
Tromino(a,tr+s-1,tc+s-1,tr,tc,s);
Tromino(a,tr+s-1,tc+s,tr,tc+s,s);
}
}
}
main() {
int i,j,dr,dc, a[N][N]; printf("please input dr(0<dr<%d):",N); scanf("%d",&dr); printf("please input dc(0<dc<%d):",N); scanf("%d",&dc); a[dr][dc]=0; Tromino(a,dr,dc,0,0,N); for(i=0;i<N;i++) {