创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡><)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
更多算法分析与设计知识专栏:算法分析
给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ
在一个2k×2k
个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为特殊方格
,且称该棋盘为特殊棋盘
。
在棋盘覆盖问题中,要用图示的4种
不同形态的L型
骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
(证明该问题有解):
数学归纳法(mathematical induction)
当n=1时(2×2棋盘),该问题有解
假设当n=k时(2k×2k棋盘),该问题有解
那么当n=k+1时(2k+1×2k+1棋盘),将棋盘划分为2k×2k子棋盘,特殊方格位于4个子棋盘之一中,余3个子棋盘中无特殊方格
利用分治法需要满足分治的条件
目前不符合将一个大问题分解成若干个与原问题相似的小问题,需要将问题进行转化
现在需要考虑如何将棋盘分为几个相同的子棋盘
我们可以将棋盘沿着它的中心进行划分,这样可以保证每个子棋盘的大小都是相同的
但是分出的棋盘中没有特殊方格,并不是特殊棋盘
如何将这3个无特殊方格的子棋盘转化为特殊棋盘?
用一个L型骨牌覆盖这3个较小棋盘的会合处,将原问题转换为`4个n=k`时的子问题,因为n=k时有解,所以n=k+1时也有解。
特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,可以用一个L型骨牌覆盖这3个较小棋盘的会合处
从而将原问题转化为4个
较小规模的棋盘覆盖问题。递归地使用这种分割,直至棋盘简化为棋盘1×1
#include
using namespace std;
int box[100][100];
int num = 0;
void chessBoard(int x, int y, int a, int b, int length)
{
//如果棋盘简化为1×1,该方格为一特殊方格
if (length == 1)
{
return;
}
int h = length / 2; //分割棋盘为原来的一半
int t = ++num; //L型骨牌号,从1开始
//左上角
if (a < x + h && b < y + h)
{ //特殊方格在此棋盘中
chessBoard(x, y, a, b, h);
}else
{ //覆盖右下角的方格再划分
box[x + h - 1][y + h - 1] = t;
chessBoard(x, y, x + h - 1, y + h- 1, h);
}
//右上角
if (a < x + h && b >= y + h)
{ //特殊方格在此棋盘中
chessBoard(x, y + h, a, b, h);
}else
{ //覆盖右下角的方格再划分
box[x + h - 1][y + h] = t;
chessBoard(x, y + h, x + h - 1, y + h, h);
}
//右下角
if (a >= x + h && b >= y + h)
{ //特殊方格在此棋盘中
chessBoard(x + h, y + h, a, b, h);
}else
{ //覆盖右下角的方格再划分
box[x + h][y + h] = t;
chessBoard(x + h, y + h, x + h, y + h, h);
}
//左下角
if (a >= x + h && b < y + h)
{ //特殊方格在此棋盘中
chessBoard(x + h, y, a, b, h);
}else
{ //覆盖右下角的方格再划分
box[x + h][y + h - 1] = t;
chessBoard(x + h, y, x + h, y + h - 1, h);
}
}
int main()
{
//左上角方格:1行1列,特殊方格:4行2列,棋盘为8×8
chessBoard(1, 1, 4, 2, 8);
for (int i = 1; i <= length; i++)
{
for (int j = 1; j <= length; j++)
{
cout << box[i][j];
}
cout << endl;
}
return 0;
}
由于覆盖一个2k×2k棋盘所需的L型骨牌个数为(4k-1)/3
,故上述算法是一个渐近意义下的最优算法。
大家的点赞、收藏、关注将是我更新的最大动力! 欢迎留言或私信建议或问题。 |
大家的支持和反馈对我来说意义重大,我会继续不断努力提供有价值的内容!如果本文哪里有错误的地方还请大家多多指出(●'◡'●) |