今天预习了棋盘覆盖算法,体会到了算法的精妙之处,刚才终于把这个程序完成了,在原有经典的代码上添加了颜色,这个纯属想玩,也感觉非常有趣。下面进入正题:
【棋盘覆盖】
首先来了解什么是特殊方格,在一个由2∧k个方格为边长组成的棋盘中,若恰有一个方格与其他方格不同,则称该方格为特殊方格,显然有4∧k中特殊方格情况。用4种不同的L型骨牌覆盖一个给定的特殊棋盘(即特殊方格的位置已经确定了)上除去特殊方格外的所有方格,且任何两个L型骨牌不得重复覆盖,我们很容易知道,除去特殊方格,剩下的方格用到的L型骨盘数恰为(4^k-1)/3。
【思路】
实现这个问题的方法其中之一就有分治法,将一个大问题,分为若干个解决办法类似的小问题来解决。可以将开始的大棋盘均分为四个小棋盘,其中原来的特殊方格一定在某一个小方格中,剩下三个没有特殊方格,若想要用分治法解决必须加上特殊方格。则需要在没有特殊方格的三个小方格角的地方分别加上一个新的特殊方格(这样三个特殊方格刚好组成一个L型骨牌),然后把这种方法递归到各个小棋盘上即可。
【源码】
#include<iostream>
#include<Windows.h>
using namespace std;
static int tile = 1;
typedef struct
{
char f;
int y;
}board;
static board **Board;
void setColor(unsigned short ForeColor = 7, unsigned short BackGroundColor = 0)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, ForeColor + BackGroundColor * 0x10);
}
void Ch(int tr, int tc, int dr, int dc, int size)
{
if (size == 1)
return;
int t = rand() % 15 + 1;
int s = size / 2;
if (dr < tr + s && dc < tc + s)
Ch(tr, tc, dr, dc, s);
else
{
Board[tr + s - 1][tc + s - 1].f = '*';
Board[tr + s - 1][tc + s - 1].y = t;
Ch(tr, tc, tr + s - 1, tc + s - 1, s);
}
if (dr < tr + s && dc >= tc + s)
Ch(tr, tc + s, dr, dc, s);
else
{
Board[tr + s - 1][tc + s].f = '*';
Board[tr + s - 1][tc + s].y = t;
Ch(tr, tc + s, tr + s - 1, tc + s, s);
}
if (dr >= tr + s && dc < tc + s)
Ch(tr + s, tc, dr, dc, s);
else
{
Board[tr + s][tc + s - 1].f = '*';
Board[tr + s][tc + s - 1].y = t;
Ch(tr + s, tc, tr + s, tc + s - 1, s);
}
if (dr >= tr + s && dc >= tc + s)
Ch(tr + s, tc + s, dr, dc, s);
else
{
Board[tr + s][tc + s].f = '*';
Board[tr + s][tc + s].y = t;
Ch(tr + s, tc + s, tr + s, tc + s, s);
}
}
int main()
{
COORD pos = { 0, 0 };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
int s = 0;
cout << "请输入棋盘边长(必须是2的整数次幂):";
cin >> s;
Board = (board**)malloc(s * sizeof(board*));
for (int i = 0; i < s; i++)
Board[i] = (board*)malloc(s * sizeof(board));
int dr, dc;
cout << "请分别输入特殊方格的行下标和纵下标" << endl;
cin >> dr >> dc;
Board[dr][dc].f = '*';
Board[dr][dc].y = 12;
Ch(0, 0, dr, dc, s);
for (int i = 0; i < s; i++)
{
for (int j = 0; j < s; j++)
{
setColor(Board[i][j].y, 0);
cout << Board[i][j].f << " ";
}
cout << endl;
}
setColor(7, 0);
for (int i = 0; i < s; i++)
free(Board[i]);
free(Board);
}
【结果】
【总结】
这个复杂的递归算法还是非常精妙的,做出来时还是很高兴的。不过美中不足的是,我用的颜色函数中,只通过单纯的随机数字来控制颜色的不同,所以运气不好时能碰到大片的颜色相同区域,不过这几率很小啦,而且影响不大,自我感jio还是阔以滴。希望大家喜欢。