棋盘覆盖算法

合集下载

棋盘覆盖算法C#

棋盘覆盖算法C#

一、实验目的:用ABCD四个字母代替四种L型骨牌,覆盖于2^kX2^k大小的棋盘中二、实验内容:在一个2^k×2^k (k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。

显然,特殊方格在棋盘中可能出现的位置有4^k种,因而有4k种不同的棋盘,图4.10(a)所示是k=2时16种棋盘中的一个。

棋盘覆盖问题(chess cover problem)要求用图4.10(b)所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

三、程序设计说明:(算法设计思路)主要思路是利用递归处理棋盘,先确定每个棋盘的特殊骨牌,然后由骨牌位置确定所摆放L型骨牌的型号,依次递归所有棋盘即得其解四、程序代码(经调试正确的源程序)using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication4{class Program{static void Main(string[] args){char[,] chessboard = new char[1000,1000];int startU = 1;int endU = 4;//在这里输入棋盘的大小int startV = 1;int endV = endU;int specialU =2;int specialV = 3;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);printchessboard(startU, endU, startV, endV,specialU,specialV, chessboard);Console.ReadLine();//************1、算法没问题,程序实现有问题,增加了L型方块编码ABCD,无形中增加了难度和代码长度,全部抛弃,无法实现,虽然很蛋疼,前后花了十几个小时//************2、问题为:递归进入某函数之后无法返回跳转到上一级函数,同一级别的棋盘递归处理之后无法处理另一同级别棋盘//************3、经过逐步执行得知程序中有一处小错误,调试之后能初步输出正确答案,在4*4规模下完全正确,在8*8规模下少一块L骨牌覆盖,说明递归还是不完全//*****经过处理已经毫无错误}public static void setblock(int startU,int endU,int startV,int endV,char[,] chessboard,int specialU,int specialV ){int style;int sizeU = endU - startU + 1;int sizeV = endV - startV + 1;if(sizeU==1) return;int midU=startU+sizeU/2-1;int midV = startV + sizeV / 2 - 1;if (specialU > midU && specialV <= midV){markSpecialBlock1style1(midU, midV, chessboard, startU, endU, startV, endV);markSpecialBlock2style1(midU, midV, chessboard, startU, endU, startV, endV);markSpecialBlock3style1(midU, midV, chessboard, startU, endU, startV, endV);setblock(midU + 1, endU, startV, midV, chessboard, specialU, specialV);//在这里尝试修改,原始数据(midU+1, endU, midV+1, endV, chessboard, specialU, specialV),改为(midU + 1, endU, startV, midV, chessboard, specialU, specialV)//haha 终于找到了哈哈原来BUG在这里在这个判断上哈哈现在问题规模不管为多大都可以了只要不超过数组大小界限return;}if (specialU <= midU && specialV <= midV){markSpecialBlock1style2(midU, midV, chessboard, startU, endU, startV, endV);markSpecialBlock2style2(midU, midV, chessboard, startU,endU, startV, endV);markSpecialBlock3style2(midU, midV, chessboard, startU, endU, startV, endV);setblock(startU, midU,startV, midV, chessboard, specialU, specialV);return;}if (specialU <= midU && specialV > midV){markSpecialBlock1style3(midU, midV, chessboard, startU, endU, startV, endV);markSpecialBlock2style3(midU, midV, chessboard, startU, endU, startV, endV);markSpecialBlock3style3(midU, midV, chessboard, startU, endU, startV, endV);setblock(startU, midU, midV + 1, endV, chessboard, specialU, specialV);return;}if (specialU > midU && specialV > midV){markSpecialBlock1style4(midU, midV, chessboard, startU,endU, startV, endV);markSpecialBlock2style4(midU, midV, chessboard, startU, endU, startV, endV);markSpecialBlock3style4(midU, midV, chessboard, startU, endU, startV, endV);setblock(midU + 1, endU, midV + 1, endV, chessboard, specialU, specialV);return;}}/*public static void isWhatStyle(int specialU,int specialV,int midU,int midV,out int style){if (specialU > midU && specialV <= midV)style = 1;else if (specialU <= midU && specialV <= midV)style = 2;else if (specialU <= midU && specialV > midV)style = 3;elsestyle = 4;return;}*///********define style1public static void markSpecialBlock1style1(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU;int specialV = midV;if (chessboard[specialU, specialV] != 0) return;//防止在棋盘中进行无限制的覆盖if (specialU >= startU && specialU <= midU && specialV >= startV && specialV <= midV)//{chessboard[specialU, specialV] = 'A';startU = startU;endU = midU;startV = startV;endV = midV;setblock(startU,endU,startV, endV, chessboard, specialU, specialV);}}public static void markSpecialBlock2style1(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU;int specialV = midV+1;if (chessboard[specialU, specialV] != 0) return;if (specialU >= startU && specialU <= midU && specialV >= midV + 1 && specialV <= endV){chessboard[specialU, specialV] = 'A';startU = startU;endU = midU;startV = midV+1;endV = endV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}public static void markSpecialBlock3style1(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU + 1;int specialV = midV + 1;if (chessboard[specialU, specialV] != 0) return;if(specialU >= midU + 1 && specialU <= endU && specialV >= midV + 1 && specialV <= endV){chessboard[specialU, specialV] = 'A';startU = midU+1;endU = endU;startV = midV + 1;endV = endV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}//********define style2public static void markSpecialBlock1style2(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU+1;int specialV = midV;if (chessboard[specialU, specialV] != 0) return;if (specialU >= midU + 1 && specialU <= endU && specialV >= startV && specialV <= midV){chessboard[specialU, specialV] = 'B';startU = midU+1;endU = endU;startV = startV;endV = midV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}public static void markSpecialBlock2style2(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU;int specialV = midV + 1;if (chessboard[specialU, specialV] != 0) return;if (specialU >= startU && specialU <= midU && specialV >= midV + 1 && specialV <= endV){chessboard[specialU, specialV] = 'B';startU = startU;endU = midU;startV = midV + 1;endV = endV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}public static void markSpecialBlock3style2(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU + 1;int specialV = midV + 1;if (chessboard[specialU, specialV] != 0) return;if (specialU >= midU + 1 && specialU <= endU && specialV >= midV + 1 && specialV <= endV){chessboard[specialU, specialV] = 'B';startU = midU + 1;endU = endU;startV = midV + 1;endV = endV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}//********define style3public static void markSpecialBlock1style3(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU;int specialV = midV;if (chessboard[specialU, specialV] != 0) return;if (specialU >= startU && specialU <= midU && specialV >= startV && specialV <= midV){chessboard[specialU, specialV] = 'C';startU = startU;endU = midU;startV = startV;endV = midV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}public static void markSpecialBlock2style3(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU + 1;int specialV = midV;if (chessboard[specialU, specialV] != 0) return;if (specialU >= midU + 1 && specialU <= endU && specialV >= startV && specialV <= midV){chessboard[specialU, specialV] = 'C';startU = midU+1;endU = endU;startV = startV;endV = midV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}public static void markSpecialBlock3style3(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU + 1;int specialV = midV + 1;if (chessboard[specialU, specialV] != 0) return;if (specialU >= midU + 1 && specialU <= endU && specialV >= midV + 1 && specialV <= endV){chessboard[specialU, specialV] = 'C';startU = midU + 1;endU = endU;startV = midV + 1;endV = endV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}//********define style4public static void markSpecialBlock1style4(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU;int specialV = midV;if (chessboard[specialU, specialV] != 0) return;if (specialU >= startU && specialU <= midU && specialV >= startV && specialV <= midV){chessboard[specialU, specialV] = 'D';startU = startU;endU = midU;startV = startV;endV = midV;setblock(startU, endU, startV, endV, chessboard, specialU,specialV);}}public static void markSpecialBlock2style4(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU;int specialV = midV + 1;if (chessboard[specialU, specialV] != 0) return;if (specialU >= startU && specialU <= midU && specialV >= midV + 1 && specialV <= endV){chessboard[specialU, specialV] = 'D';startU = startU;endU = midU;startV = midV + 1;endV = endV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}public static void markSpecialBlock3style4(int midU, int midV, char[,] chessboard, int startU, int endU, int startV, int endV){int specialU = midU + 1;int specialV = midV;if (chessboard[specialU, specialV] != 0) return;if (specialU >= midU + 1 && specialU <= endU && specialV >= startV && specialV <= midV){chessboard[specialU, specialV] = 'D';startU = midU + 1;endU = endU;startV = startV;endV = midV;setblock(startU, endU, startV, endV, chessboard, specialU, specialV);}}//*********print chessboardpublic static void printchessboard(int startU,int endU,int startV,int endV,int specialU,int specialV,char[,] chessboard){for (int i = startV; i <= endV; i++){for (int j = startU; j <= endU; j++){if(j==specialU&&i==specialV)Console.Write('S'+" ");elseConsole.Write(chessboard[j, i]+" ");}Console.WriteLine();}}}}五.程序运行结果(测试数据和运行结果)。

棋盘覆盖问题(Tromino谜题)

棋盘覆盖问题(Tromino谜题)

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]);

棋盘8x8的覆盖问题,其中一个点已经被覆盖,用l型模块将其余完全覆盖的分治策略.约

棋盘8x8的覆盖问题,其中一个点已经被覆盖,用l型模块将其余完全覆盖的分治策略.约

棋盘8x8的覆盖问题,其中一个点已经被覆盖,用l型模块将其余完全覆盖的分治策略.约【算法】分治策略之棋盘覆盖问题
问题:
在一个{2}^{k}*{2}^{k}个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。

在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

策略:
将棋盘分割成四个大小相等的子棋盘,则特殊方格必位于4个较小子棋盘之一中,其余三个无特殊方格。

为了将这3个子棋盘转化为特殊棋盘,可以用一个L
形骨牌覆盖这三个较小棋盘的汇合处,这三个子棋盘被骨牌覆盖的方格就成为该棋盘上的特殊方格,从而将问题转化为四个较小规模的棋盘覆盖问题。

递归地分割棋盘,直到简化为1*1的棋盘。

棋盘覆盖问题的求解

棋盘覆盖问题的求解

棋盘覆盖问题的求解棋盘覆盖问题是一个经典的数学问题,它引发了人们对于数学中的逻辑思维和问题解决能力的思考。

在这篇文章中,我将为大家详细介绍棋盘覆盖问题的求解方法,并希望能够帮助中学生和他们的父母更好地理解和应用这一问题。

棋盘覆盖问题是指如何用特殊形状的骨牌将一个2^n × 2^n的棋盘完全覆盖的问题。

其中,骨牌的形状分为4种,分别为L型、反L型、凸型和凹型。

在求解这个问题时,我们需要遵循以下几个步骤。

首先,我们需要将给定的棋盘划分为四个相等的小棋盘。

这样,我们就可以将问题分解为四个子问题,分别是将四个小棋盘覆盖完整。

接下来,我们就可以通过递归的方式来解决每个子问题。

在解决子问题时,我们需要根据骨牌的形状来选择放置的位置。

以L型骨牌为例,我们可以将其放置在左上角、左下角或者右上角。

通过不同的放置位置,我们可以将子问题进一步分解为更小的子问题。

同样地,我们可以使用相同的方法来解决反L型、凸型和凹型骨牌。

在每个子问题中,我们需要注意两个关键点。

首先,我们需要保证每个小棋盘上的骨牌能够完全覆盖。

这就要求我们在放置骨牌时,需要选择合适的位置和方向。

其次,我们需要保证四个小棋盘的边缘能够对齐。

这样,才能保证最终的结果是一个完整的棋盘。

通过不断地递归求解子问题,我们最终可以将整个棋盘完全覆盖。

这个过程中,我们需要注意边界条件的处理,以及递归函数的设计。

同时,我们还可以通过剪枝等优化方法来提高算法的效率。

棋盘覆盖问题的求解方法不仅仅是一个数学问题,更是一个思维训练的过程。

通过解决这个问题,我们可以培养自己的逻辑思维能力、问题解决能力和创新思维。

同时,这个问题也具有一定的实用性,可以用于解决一些实际问题,如图像处理、计算机视觉等领域。

总结一下,棋盘覆盖问题是一个经典的数学问题,通过将棋盘划分为四个小棋盘,我们可以通过递归的方式来解决每个子问题。

在解决子问题时,我们需要选择合适的骨牌形状和放置位置,同时保证边缘对齐和完全覆盖。

棋盘覆盖问题c语言

棋盘覆盖问题c语言
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,dr,dc,s);
else
{//特此棋盘中无特殊方格 ,t号L型骨牌覆盖左下角
{//此棋盘中无特殊方格 ,t号L型骨牌覆盖左上角
board[tr+s][tc+s]=t;
// 覆盖本子棋盘中的其余方格
ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
int main()
{
int size,r,c,row,col;
printf("输入棋盘大小:\n");
scanf("%d",&size);//输入棋盘大小
{
for (c = 0; c < size; c++)
{
printf("%d ",board[r][c]);
}
printf("\n");
}
return 0;
}
运行效果:
实验报告成绩
老师
注:1)专业班级按打印课表中名称填写;2)课程名称按课表中名称填写,不能简写;
3)实验日期格式示例:)实验时间格式示例:“第三大节”5)实验情况包括任务(或题目)、解决方案(或者代码)、结果等;6)实验报告成绩按五级标准评分;精心搜集整理,只为你的需要

棋盘覆盖问题算法思路

棋盘覆盖问题算法思路

棋盘覆盖问题算法思路
棋盘覆盖问题是一道经典的分治算法问题,通常用于介绍分治算法的思想。

其基本思路是将棋盘分成若干个小块,然后在其中一个小块上放置一块特殊的骨牌,然后将剩下的小块按照同样的方式继续分成更小的块,并在其中一个小块上放置另一块骨牌,以此类推,直到整个棋盘被覆盖。

具体的实现过程可以采用递归的方式,将棋盘不断地分成四个部分,然后在其中一个部分上放置一块骨牌,再递归求解另外三个部分。

在实现过程中,需要注意处理边界条件和特殊情况,例如棋盘大小为1x1或者存在特殊方块无法覆盖等情况。

该算法的时间复杂度为O(2^n),其中n为棋盘大小的指数。

虽然时间复杂度较高,但是由于该问题特殊的递归性质使得其能够被高效地并行化,因此在实际应用中仍有广泛的应用。

分治法棋盘覆盖问题算法原理

分治法棋盘覆盖问题算法原理

分治法棋盘覆盖问题算法原理
分治法棋盘覆盖问题算法是一种基于分治策略的算法,用于解决棋盘覆盖问题。

该算法的基本原理是将一个复杂的问题分解为若干个较小的子问题,然后分别求解这些子问题,最后将子问题的解合并为原问题的解。

在棋盘覆盖问题中,给定一个n×n的棋盘,要求用最少的1×2骨牌覆盖整个棋盘。

分治法棋盘覆盖问题算法通过将棋盘不断划分,将问题规模逐渐减小,最终将问题转化为若干个1×1的棋盘覆盖问题,从而使得问题得以解决。

具体来说,该算法首先将棋盘划分为四个相等的子棋盘,然后判断哪个子棋盘中包含特殊方格。

对于不包含特殊方格的子棋盘,用L型骨牌覆盖其会合处,将其转化为特殊棋盘。

然后递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。

通过这种分治策略,算法可以将问题规模不断减小,直到每个子问题都能够被直接解决。

最终,所有子问题的解将被合并为原问题的解。

这种算法不仅具有高效性,而且能够将复杂的问题分解为若干个简单的子问题,使得问题的解决更加容易。

棋盘覆盖算法

棋盘覆盖算法

棋盘覆盖算法
棋盘覆盖算法是一种使用分治策略来覆盖一个给定的棋盘的算法。

其基本思想是将棋盘划分成四个等分的子棋盘,然后从中选择一个作为特殊方格,并在其它三个子棋盘上递归执行该算法。

这个过程会一直递归下去,直到棋盘被完全覆盖。

在实际应用中,棋盘覆盖算法可以用来解决一些与棋盘相关的问题,例如:在一个棋盘上,如何用L型骨牌覆盖所有格子?如何在一个棋盘上放置n个皇后,使得它们不互相攻击?
棋盘覆盖算法的时间复杂度为O(2^n),因此在处理大规模的棋盘问题时,可能会存在效率问题。

为了提高算法的效率,可以考虑使用一些优化技巧,例如:使用启发式搜索来减少搜索空间,或者使用记忆化搜索来避免重复计算。

总之,棋盘覆盖算法是一种十分有用的算法,在许多棋盘相关的问题中都能够得到应用。

- 1 -。

棋盘覆盖问题算法思路

棋盘覆盖问题算法思路

棋盘覆盖问题算法思路棋盘覆盖问题是一个经典的递归问题,其原始问题定义如下:给定一个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. 最终,我们找到的正确的解决方案就是把所有多米诺骨牌都放置在位置上的布局。

总之,棋盘覆盖算法是一个重要的问题,它在计算机科学领域中具有广泛的应用。

在实际应用中,我们可以使用计算机来解决这个问题,例如利用回溯算法。

棋盘覆盖问题(算法竞赛入门经典)

棋盘覆盖问题(算法竞赛入门经典)

棋盘覆盖问题(算法竞赛⼊门经典)在⼀个 2^k * 2^k 个⽅格组成的棋盘中,若恰有⼀个⽅格与其它⽅格不同,则称该⽅格为⼀特殊⽅格,称该棋盘为⼀特殊棋盘。

显然特殊⽅格在棋盘上出现的位置有 4^k 种情形。

因⽽对任何 k>=0 ,有 4^k 种不同的特殊棋盘。

下图所⽰的特殊棋盘为 k=2 时 16 个特殊棋盘中的⼀个。

在棋盘覆盖问题中,要⽤下图中 4 中不同形态的 L 型⾻牌覆盖⼀个给定的特殊棋牌上除特殊⽅格以外的所有⽅格,且任何 2 个 L 型⾻牌不得重叠覆盖。

易知,在任何⼀个 2^k * 2^k 的棋盘中,⽤到的 L 型⾻牌个数恰为 (4^k-1)/3 。

⽤分治策略,可以设计解棋盘问题的⼀个简捷的算法。

当 k>0 时,将 2^k * 2^k 棋盘分割为 4 个 2^(k-1) * 2^(k-1) ⼦棋盘,如下图所⽰。

特殊⽅格必位于 4 个较⼩⼦棋盘之⼀中,其余 3 个⼦棋盘中⽆特殊⽅格。

为了将这 3 个⽆特殊⽅格的⼦棋盘转化为特殊棋盘,我们可以⽤⼀个 L 型⾻牌覆盖这 3 个较⼩的棋盘的汇合处,如下图所⽰,这 3 个⼦棋盘上被 L 型⾻牌覆盖的⽅格就成为该棋盘上的特殊⽅格,从⽽将原问题化为 4 个较⼩规模的棋盘覆盖问题。

递归的使⽤这种分割,直⾄棋盘简化为 1x1 棋盘。

下⾯给出代码:1 #include<iostream>2 #include<string.h>3 using namespace std;4 int tile=1; //L型⾻牌的编号(递增)5 int board[100][100]; //棋盘6 /*****************************************************7 * 递归⽅式实现棋盘覆盖算法8 * 输⼊参数:9 * tr--当前棋盘左上⾓的⾏号10 * tc--当前棋盘左上⾓的列号11 * dr--当前特殊⽅格所在的⾏号12 * dc--当前特殊⽅格所在的列号13 * size:当前棋盘的:2^k14 *****************************************************/15 void chessBoard ( int tr, int tc, int dr, int dc, int size )16 {17 if ( size==1 ) //棋盘⽅格⼤⼩为1,说明递归到最⾥层18 return;19 int t=tile++; //每次递增120 int s=size/2; //棋盘中间的⾏、列号(相等的)21 //检查特殊⽅块是否在左上⾓⼦棋盘中22 if ( dr<tr+s && dc<tc+s ) //在23 chessBoard ( tr, tc, dr, dc, s );24 else //不在,将该⼦棋盘右下⾓的⽅块视为特殊⽅块25 {26 board[tr+s-1][tc+s-1]=t;27 chessBoard ( tr, tc, tr+s-1, tc+s-1, s );28 }29 //检查特殊⽅块是否在右上⾓⼦棋盘中30 if ( dr<tr+s && dc>=tc+s ) //在31 chessBoard ( tr, tc+s, dr, dc, s );32 else //不在,将该⼦棋盘左下⾓的⽅块视为特殊⽅块33 {34 board[tr+s-1][tc+s]=t;35 chessBoard ( tr, tc+s, tr+s-1, tc+s, s );36 }37 //检查特殊⽅块是否在左下⾓⼦棋盘中38 if ( dr>=tr+s && dc<tc+s ) //在39 chessBoard ( tr+s, tc, dr, dc, s );40 else //不在,将该⼦棋盘右上⾓的⽅块视为特殊⽅块41 {42 board[tr+s][tc+s-1]=t;43 chessBoard ( tr+s, tc, tr+s, tc+s-1, s );44 }45 //检查特殊⽅块是否在右下⾓⼦棋盘中46 if ( dr>=tr+s && dc>=tc+s ) //在47 chessBoard ( tr+s, tc+s, dr, dc, s );48 else //不在,将该⼦棋盘左上⾓的⽅块视为特殊⽅块49 {50 board[tr+s][tc+s]=t;51 chessBoard ( tr+s, tc+s, tr+s, tc+s, s );52 }53 }5455 int main()56 {57 int size;58 memset(board,0,sizeof(board));59 cout<<"输⼊棋盘的size(⼤⼩必须是2的n次幂): ";60 cin>>size;61 int index_x,index_y;62 cout<<"输⼊特殊⽅格位置的坐标: ";63 cin>>index_x>>index_y;64 cout<<board[index_x][index_y]<<endl;65 chessBoard ( 0,0,index_x,index_y,size );66 for ( int i=0; i<size; i++ )67 {68 for ( int j=0; j<size; j++ )69 cout<<board[i][j]<<' ';70 cout<<endl;71 }72 return 0;73 }。

棋盘覆盖问题的算法实现(代码及截图)

棋盘覆盖问题的算法实现(代码及截图)

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

棋盘覆盖算法

棋盘覆盖算法

棋盘覆盖算法
棋盘覆盖算法是一种经典的计算机算法,主要用于解决棋盘覆盖问题。

棋盘覆盖问题是指,将一个大小为2的幂次方的棋盘分成若干个大小为2的幂次方的小棋盘,然后选择其中一个小棋盘覆盖一个方块,直到所有方块都被覆盖。

具体规则是,每次覆盖一个小棋盘,然后将其他小棋盘划分成4个等分的小棋盘,其中一个小棋盘被覆盖,而其他小棋盘继续重复这个过程,直到所有方块都被覆盖。

棋盘覆盖算法可以采用分治算法的思想,将棋盘分成四个小区域,然后递归地解决每个小区域的棋盘覆盖问题。

每个小区域可以采用类似的方法继续划分,直到小棋盘的大小为1。

然后根据特定规则选择一个小棋盘进行覆盖,再递归地解决其他小区域的棋盘覆盖问题。

棋盘覆盖算法的时间复杂度为O(n^2),其中n为棋盘的大小。

虽然该算法的复杂度比较高,但是它可以解决一些实际问题,比如图像识别、计算机视觉等。

- 1 -。

棋盘覆盖问题 C语言

棋盘覆盖问题 C语言
printf("输入特殊方格位置:row,col \n");
scanf("%d,%d",&row,&col);//输入特殊方格位置
ChessBoard(0,0,row,col,size);
printf("输出棋盘覆盖结果:\n");
for (r = 0; r < size; r++)//输出棋盘覆盖结果
{
if(size==1) return;//递归边界
int t=tile++;//L型骨牌号
int s=size/2;//分割棋盘
//覆盖左上角子棋盘
if(dr<tr+s&&dc<tc+s)
// 特殊方格在此棋盘中
ChessBoard(tr,tc,dr,dc,s);
else
{ //此棋盘中无特殊方格 ,用t号L型骨牌覆盖右下角
实验报告
学号
54141325ห้องสมุดไป่ตู้107
姓名
高行行
专业班级
移动互联网14-01
课程
算法分析与设计
实验日期
2016.9.29
实验时间
8:00-9:00
实验情况
备注
棋盘覆盖问题算法:
#include<stdio.h>
int tile=1;
int board[100][100];
void ChessBoard(int tr,int tc,int dr,int dc,int size)
board[tr+s][tc+s-1]=t;
// 覆盖本子棋盘中的其余方格

棋盘覆盖问题

棋盘覆盖问题

问题分析(二)
(2)用一个L型骨牌覆盖这3个较小棋盘的结合处。(
如图(d))
(d) 构造相同子问题
这3个子棋盘上被L型骨牌覆盖的方格就成为该 棋盘上的残缺方格,原问题转化为4个较小规模的 棋盘覆盖问题。递归地使用这种分割,直至棋盘 简化为11棋盘。
详Hale Waihona Puke 过程图解如下棋盘中有一个特殊方格
第一次分割
棋盘覆盖问题
问题描述(一)
在一个 k 2k(k≥0)个方格组成的棋盘中, 2 恰有一个方格与其他方格不同,称该方格为特 殊方格,显然,特殊方格在棋盘中出现的位置 有4 k 中情形,因而有4 k 中不同的棋盘(如图 (a) )。
(a) k=2时的一种棋盘
问题描述(二)
棋盘覆盖问题要求用如图(b)所示的L型骨牌覆 盖给定棋盘上除特殊方格以外的所有方格,且任 何2个L型骨牌不得重叠覆盖。
// 覆盖右上角子棋盘 if (dr < tr + s && dc >= tc + s) // 特殊方格在右上角子棋盘中 ChessBoard(tr, tc+s, dr, dc, s); //递归处理子棋盘 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) // 特殊方格在左下角子棋盘中 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); } // 覆盖右下角子棋盘 if (dr >= tr + s && dc >= tc + s) // 特殊方格在右下角子棋盘中 ChessBoard(tr+s, tc+s, dr, dc, s); //递归处理子棋盘 else { // 用 t 号L型骨牌覆盖左上角,再递归处理子棋盘 board[tr + s][tc + s] = t; ChessBoard(tr+s, tc+s, tr+s, tc+s, s); } }

关于棋盘覆盖问题的算法(C++) [当文网提供]

关于棋盘覆盖问题的算法(C++) [当文网提供]

分治法解决棋盘覆盖问题By Aillo on April 9, 2008 10:22 PM |0 Comments | Previous | Next | EDIT在一个2k x 2k ( 即:2^k x 2^k )个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。

在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

这里我们用分治法解决该问题。

分治法是把一个规模很大的问题分解为多个规模较小、类似的子问题,然后递归地解决所有子问题,最后再由子问题的解决得到原问题的解决。

【解题思路】:将2^k x 2^k的棋盘,先分成相等的四块子棋盘,其中特殊方格位于四个中的一个,构造剩下没特殊方格三个子棋盘,将他们中的也假一个方格设为特殊方格。

如果是:左上的子棋盘(若不存在特殊方格)----则将该子棋盘右下角的那个方格假设为特殊方格右上的子棋盘(若不存在特殊方格)----则将该子棋盘左下角的那个方格假设为特殊方格左下的子棋盘(若不存在特殊方格)----则将该子棋盘右上角的那个方格假设为特殊方格右下的子棋盘(若不存在特殊方格)----则将该子棋盘左上角的那个方格假设为特殊方格当然上面四种,只可能且必定只有三个成立,那三个假设的特殊方格刚好构成一个L型骨架,我们可以给它们作上相同的标记。

这样四个子棋盘就分别都和原来的大棋盘类似,我们就可以用递归算法解决。

代码如下:#include<iostream.h>int tile=1;int board[100][100];void chessBoard(int tr, int tc, int dr, int dc, int size) {if(size==1)return;int t=tile++;int 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 size;cout<<"输入棋盘的size(大小必须是2的n次幂): ";cin>>size;int index_x,index_y;cout<<"输入特殊方格位置的坐标: ";cin>>index_x>>index_y;chessBoard(0,0,index_x,index_y,size);for(int i=0;i<size;i++){for(int j=0;j<size;j++)cout<<board[i][j]<<"\t";cout<<endl;}}关于棋盘覆盖问题的算法(C++)//程序说明:1):讲一下代码拷贝到vc6.0(或其他支持的IDE环境)下,执行后会生成一个// input.txt文件,打开将里面的参数换成你想设计的再执行程序就OK了!// 2):如果对代码理解不透,建议使用但不调试,检测每一步的执行情况// 3):本程序仅供学习参考使用,用完请删除#include<stdio.h>#include<fstream.h>#include<iomanip.h>#include<iostream.h>#include<stdlib.h>int tile=0; //定义全局变量tile表示L型骨牌编号int **chessarr; //定义全局变量chessarr表示棋盘数组void chessboard(int row0,int col0,int size,int sprow,int spcol);// 棋盘覆盖函数// row0,col0为棋盘左上角位置,sprow,spcol为特殊方格位置// size为棋盘规模void chessboard(int row0,int col0,int size,int sprow,int spcol) //棋盘覆盖函数{if(size==1) return; //如果棋盘规模=1,返回int s=size/2; //分割棋盘int t=++tile; //L型骨牌编号加1//处理左上角子棋盘if(sprow < row0+s && spcol < col0+s)chessboard(row0,col0,s,sprow,spcol);else{chessarr[row0+s-1][col0+s-1]=t;chessboard(row0,col0,s,row0+s-1,col0+s-1);}//处理右上角子棋盘if(sprow < row0+s && spcol >= col0+s)chessboard(row0,col0+s,s,sprow,spcol);else{chessarr[row0+s-1][col0+s]=t;chessboard(row0,col0+s,s,row0+s-1,col0+s);}//处理左下角子棋盘if(sprow >= row0+s && spcol < col0+s)chessboard(row0+s,col0,s,sprow,spcol);else{chessarr[row0+s][col0+s-1]=t;chessboard(row0+s,col0,s,row0+s,col0+s-1);}//处理右下角子棋盘if(sprow >= row0+s && spcol >= col0+s)chessboard(row0+s,col0+s,s,sprow,spcol);else{chessarr[row0+s][col0+s]=t;chessboard(row0+s,col0+s,s,row0+s,col0+s);}}void main(){int k,x,y; //阶数及特殊点位置int i,j,n; //棋盘规模为n*nifstream in("input.txt"); //打开输入文件if(in.fail()){cout << "the input.txt is not exist!";exit(1);}in>>k>>x>>y; //读入阶数k和特殊方格位置in.close(); //关闭输入文件if (k<1){cout << "K<1, Error input.txt!";exit (1);}for (i=0,n=1;i<k;i++)n*=2;//在堆内存中建立棋盘数组,填充特殊方格if((chessarr=new int*[n])==NULL){cout << "Can't allocate more memory,terminating." << endl;exit (1);}for (i=0;i<n;i++ ){if((chessarr[i]=new int[n])==NULL){cout << "Can't allocate more memory,terminating." << endl;exit (1);}}chessarr[x-1][y-1]=0; // 填写特殊方格tile=0;chessboard(0,0,n,x-1,y-1);//进行棋盘覆盖,左上角位置0,0; 棋盘宽度n; 特殊点x,y ofstream out("output.txt"); //创建输出文件//同时输出到文件和屏幕for (i=0;i<n;i++){for (j=0;j<n;j++ ){out << setw(5) << chessarr[i][j];cout << setw(5) << chessarr[i][j];}out << endl;cout << endl;}out.close(); //关闭输出文件//释放内存for(i=0;i<n;i++)delete[] chessarr[i];delete[] chessarr;return;}矩阵快速乘法矩阵相乘在3D变换中是被频繁用到的一种计算,但在矩阵相乘过程中用到了大量的乘法运算,而cpu中运算单元对于乘法的效率是比较低的,远低于加法运算,所以,如果能找到一种用加法来替代乘法的方法实现矩阵相乘,将能大大提高我们程序的效率。

棋盘覆盖(算法实验代码)

棋盘覆盖(算法实验代码)

实验一、棋盘覆盖代码及截图代码:#include <stdio.h>int tile=1;int Board[32][32];void ChessBoard(int tr,int tc,int dr,int dc,int size){if(size==1) return;int t=tile++;int 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 size;printf("请输入棋盘的大小(大小为2的N次方):");scanf("%d",&size);int x,y;printf("请输入特殊方格的坐标:");scanf("%d %d",&x,&y);ChessBoard(0,0,x,y,size);for(int i=0;i<size;i++){for(int j=0;j<size;j++)printf("%2d ",Board[i][j]);printf("\n");}}截图:。

分治算法--棋盘覆盖

分治算法--棋盘覆盖

分治算法--棋盘覆盖问题描述在⼀个2^k×2^k个⽅格组成的棋盘中,恰有⼀个⽅格与其他⽅格不同,称该⽅格为⼀特殊⽅格,且称该棋盘为⼀特殊棋盘。

在棋盘覆盖问题中,要⽤图⽰的4种不同形态的L型⾻牌覆盖给定的特殊棋盘上除特殊⽅格以外的所有⽅格,且任何2个L型⾻牌不得重叠覆盖。

解题思路分析:当k>0时,将2k×2k棋盘分割为4个2^k-1×2^k-1⼦棋盘(a)所⽰。

特殊⽅格必位于4个较⼩⼦棋盘之⼀中,其余3个⼦棋盘中⽆特殊⽅格。

为了将这3个⽆特殊⽅格的⼦棋盘转化为特殊棋盘,可以⽤⼀个L型⾻牌覆盖这3个较⼩棋盘的会合处,如 (b)所⽰,从⽽将原问题转化为4个较⼩规模的棋盘覆盖问题。

递归地使⽤这种分割,直⾄棋盘简化为棋盘1×1。

(出⾃算法设计与分析-王晓东)实现:每次都对分割后的四个⼩⽅块进⾏判断,判断特殊⽅格是否在⾥⾯。

这⾥的判断的⽅法是每次先记录下整个⼤⽅块的左上⾓(top left coner)⽅格的⾏列坐标,然后再与特殊⽅格坐标进⾏⽐较,就可以知道特殊⽅格是否在该块中。

如果特殊⽅块在⾥⾯,这直接递归下去求即可,如果不在,这根据分割的四个⽅块的不同位置,把右下⾓、左下⾓、右上⾓或者左上⾓的⽅格标记为特殊⽅块,然后继续递归。

在递归函数⾥,还要有⼀个变量s来记录边的⽅格数,每次对⽅块进⾏划分时,边的⽅格数都会减半,这个变量是为了⽅便判断特殊⽅格的位置。

其次还要有⼀个变nCount来记录L型⾻牌的数量。

代码实现:#include <stdio.h>#include <stdlib.h>int nCount = 0;int Matrix[100][100];void chessBoard(int tr, int tc, int dr, int dc, int size);int main(){int size,r,c,row,col;memset(Matrix,0,sizeof(Matrix));scanf("%d",&size);scanf("%d%d",&row,&col);chessBoard(0,0,row,col,size);for (r = 0; r < size; r++){for (c = 0; c < size; c++){printf("%2d ",Matrix[r][c]);}printf("\n");}return0;}void chessBoard(int tr, int tc, int dr, int dc, int size){//tr and tc represent the top left corner's coordinate of the matrixint s,t;if (1 == size) return;s = size/2; //The number of grid the matrix's edget = ++ nCount;//locate the special grid on bottom right cornerif (dr < tr + s && dc < tc +s){chessBoard(tr,tc,dr,dc,s);}else{Matrix[tr+s-1][tc+s-1] = t;chessBoard(tr,tc,tr+s-1,tc+s-1,s);}//locate the special grid on bottom left cornerif (dr < tr + s && dc >= tc + s ){chessBoard(tr,tc+s,dr,dc,s);}else{Matrix[tr+s-1][tc+s] = t;chessBoard(tr,tc+s,tr+s-1,tc+s,s);}//locate the special grid on top right corner if (dr >= tr + s && dc < tc + s){chessBoard(tr+s,tc,dr,dc,s);}else{Matrix[tr+s][tc+s-1] = t;chessBoard(tr+s,tc,tr+s,tc+s-1,s);}//locate the special grid on top left corner if (dr >= tr + s && dc >= tc + s){chessBoard(tr+s,tc+s,dr,dc,s);}else{Matrix[tr+s][tc+s] = t;chessBoard(tr+s,tc+s,tr+s,tc+s,s);}}2013/6/14 22:30程序结果:。

棋盘覆盖问题(C++实现)

棋盘覆盖问题(C++实现)

棋盘覆盖问题(C++实现)在⼀个2k×2k 个⽅格组成的棋盘中,恰有⼀个⽅格与其它⽅格不同,称该⽅格为⼀特殊⽅格,且称该棋盘为⼀特殊棋盘。

问题: ⽤4种不同形态的L型⾻牌, 覆盖给定特殊棋盘上除特殊⽅格以外的所有⽅格,且任何2个不得重叠。

特殊⽅格在棋盘上出现的位置有4k种情形。

因⽽对任何k>=0,有4k种不同的特殊棋盘。

易知,在任何⼀个2k * 2k的棋盘中,⽤到的L型⾻牌个数恰为(4k -1)/3。

1. 当k>0时,将2k×2k棋盘分割为4个2k-1×2k-1 ⼦棋盘, Figure (a)所⽰。

2. 特殊⽅格必位于4个较⼩⼦棋盘之⼀中,其余3个⼦棋盘中⽆特殊⽅格。

3. 为将⽆特殊⽅格⼦棋盘转化为特殊棋盘,可以⽤⼀个⾻牌覆盖3个较⼩棋盘的会合处,如 Figure(b)所⽰,从⽽将原问题转化为4个较⼩规模的棋盘覆盖问题。

4. 递归地使⽤这种分割,直⾄棋盘简化为棋盘1×1。

#include<iostream>using namespace std;int tile=1; //L型⾻牌的编号(递增)int Board[100][100]; //棋盘/****************************************************** 递归⽅式实现棋盘覆盖算法* 输⼊参数:* tr--当前棋盘左上⾓的⾏号* tc--当前棋盘左上⾓的列号* dr--当前特殊⽅格所在的⾏号* dc--当前特殊⽅格所在的列号* size:当前棋盘的:2^k*****************************************************/void ChessBoard(int tr,int tc,int dr,int dc,int size){if(size==1) return;int t=tile++,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;///⽤t号(⽤⼀个数字表⽰)L型⾻牌覆盖右下⾓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);}}int main(){int size;cout<<"输⼊棋盘的size(⼤⼩必须是2的n次幂): ";cin>>size;int index_x,index_y;cout<<"输⼊特殊⽅格位置的坐标: ";cin>>index_x>>index_y;ChessBoard ( 0,0,index_x-1,index_y-1,size );for ( int i=0; i<size; i++ ){for ( int j=0; j<size; j++ )cout<<Board[i][j]<<'\t';cout<<endl;}}推导过程: 原式等价于 T(k)=4T(k-1)+1递推得: 4T(k-1)=4(4T(k-2)+1)=42T(k-2)+4 T(k)= 42T(k-2)+4 +1⼜有: 42T(k-2)=43T(k-3)+42故 T(k)= 43T(k-3)+42+4+1………………….T(k)=4kT(0)+4k-1+…+4+1=O(4k)。

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

用Visual C++实现棋盘覆盖分治算法
一、问题描述
在一个k k 22⨯个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘唯一特殊棋盘。

在棋盘覆盖问题中,要用4种不同形态的L 型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L 型骨牌不得重叠覆盖。

当0k >时,将k k 22⨯棋盘分割为4个1-k 1-k 22⨯子棋盘,特殊方格必位于4个较小子棋盘之一中,将其余3个子棋盘中无特殊方格。

为了将这3个无特殊方格子棋盘转化为特殊棋盘,可以用一个L 型骨牌覆盖着3个较小棋盘的会合处,从而将原问题转化为4个较小规模的棋盘覆盖问题。

递归的使用这种分割,直至棋盘转化为棋盘11⨯。

二、程序
(1)新建一个基于对话框的工程Ex0420Chess 。

(2)打开类视图,为CEx0420ChessDlg 类添加以下成员变量和函数:
int tile; //当前方块
int **board;
//指向棋盘的指针 int m_dw; //棋盘每一格的宽度
void chessBoard(int tr, int tc, int dr, int dc, int size); //棋盘覆盖算法
void DrawSubBoard(int x, int y, int w, int c); //画棋盘的x行,y列的方块,w表示宽度,c表示颜色值
(3)在对话框上增加三个编辑框,ID分别IDC_K、IDC_DR和IDC_DC,并为他们分别关联一个int型的变量m_k、m_dr和m_dc。

然后添加三个按钮,ID分别为IDC_DRAW、IDC_DRAWBOAR和DIDC_CLEAR,标题分别为画棋盘、覆盖和清空。

256 ,k值越大,方格越(4)本实验棋盘的大小固定为256
多,这时每个方格的尺寸越小。

为给每个L型骨牌填充不同的颜色,程序中将title的值转换成颜色值,画一个方格的函数DrawSubBoard()的定义如下:
void CEx0420ChessDlg::DrawSubBoard(int x ,int y ,int w, int c)
{
CClientDC dc(this);
COLORREF clr;
clr= RGB(c*c/256,c*c*c/256,c*c*c*c/256); //将c值转换成颜色值
CBrush br(clr);
CRect r;
=10+x*m_dw;
=+m_dw;
=10+y*m_dw;
=+m_dw;
(&r,&br);
}
使用分治算法覆盖棋盘,为清楚看到覆盖棋盘的顺序,每次覆盖完一个L型骨牌后停顿秒,chessBoard()函数源程序如下:
void CEx0420ChessDlg::chessBoard(int tr, int tc, int dr, int dc, int size)
{
if (size == 1) return;
Sleep(500);
int t = this->tile++; // L型骨牌号
int s = size/2; // 分割棋盘
// 覆盖左上角子棋盘
if (dr < tr + s && dc < tc + s) // 特殊方格在此棋盘中chessBoard(tr, tc, dr, dc, s);
else
{// 此棋盘中无特殊方格用t 号L型骨牌覆盖右下角
board[tr + s - 1][tc + s - 1] = t; // 覆盖其余方格
chessBoard(tr, tc, tr+s-1, tc+s-1, s);
this->DrawSubBoard(tr+s-1, tc+s-1,m_dw,t); //递归过程中,此子棋盘中没有特殊方格,调用DrawSubBoard()函数画一个方
格,并填充颜色
}
// 覆盖右上角子棋盘
if (dr < tr + s && dc >= tc + s)
// 特殊方格在此棋盘中
chessBoard(tr, tc+s, dr, dc, s);
else// 此棋盘中无特殊方格
{// 用t 号L型骨牌覆盖左下角
board[tr + s - 1][tc + s] = t;
// 覆盖其余方格
chessBoard(tr, tc+s, tr+s-1, tc+s, s);
this->DrawSubBoard(tr+s-1, tc+s,m_dw,t); }
// 覆盖左下角子棋盘
if (dr >= tr + s && dc < tc + s)
// 特殊方格在此棋盘中
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);
this->DrawSubBoard(tr+s, tc+s-1,m_dw,t);
}
// 覆盖右下角子棋盘
if (dr >= tr + s && dc >= tc + s)
// 特殊方格在此棋盘中
chessBoard(tr+s, tc+s, dr, dc, s);
else
{// 用t 号L型骨牌覆盖左上角
board[tr + s][tc + s] = t;
// 覆盖其余方格
chessBoard(tr+s, tc+s, tr+s, tc+s, s);
this->DrawSubBoard(tr+s, tc+s,m_dw,t);
}
}
(5)为三个按钮分别添加消息响应函数
//点击“画棋盘”按钮消息响应函数
void CEx0420ChessDlg::OnDraw()
{
UpdateData(); //更新编辑框中的数据,重要
if(m_k>5)
this->MessageBox("为了方便演示,建议输入1-5的整数");
else{
this->OnClear();
CClientDC dc(this); //当输入一个新的k值时,清空原有图形
int k=this->m_k;
this->m_dw=256/(int)pow(2,k);//棋盘区域大小固定为256*256,根据k值计算方格宽度
for(int i=10;i<267;i+=m_dw) //画棋盘
{
(10,i);
(267,i);
(i,10;
(i,267);
}
}
}
//点击“覆盖”按钮消息响应函数
Void CEx0420ChessDlg::Ondrawboard()
{
UpdateData();
if(m_dr>=(int)pow(2,m_k)||m_dc>=(int)pow(2,m_k)||m_dr<0|| m_dc<0)
//判断dr,dc中数据是否溢出
this->MessageBox("特殊方格行号或列号错误,请重新输入!");
else{
this->OnClear();
this->OnDraw();
CClientDC dc(this);
COLORREF clr;
clr = RGB(0,0,0);
CBrush br(clr);
CRect r;
int w = 256/(int)pow(2,m_k);
= 10+m_dr*w;
= +w;
= 10+m_dc*w;
= +w;
(&r,&br);
Sleep(1000);
this->chessBoard(0,0,this->m_dr,this->m_dc,(int)pow(2,this->m_k));
}
}
void CEx0420ChessDlg::Onclear()
{
CClientDC dc(this);
(10,10,267,267);
}
二,注意
本程序定义了一个指向指针的指针**board,在使用时必须进行初始化,初始化的方法为:
board = new int *[50];
for(int i=0;i<50;i++)
board[i]=new int[50];。

相关文档
最新文档