题目:有一个 2 k ∗ 2 k 2^k*2^k 2k∗2k的方格棋盘,恰有一个方格是黑色的,其他为白色。你的任务是用包含3个方格的L型牌覆盖所有白色方格。黑色方格不能被覆盖,且任意一个白色方格不能同时被两个或更多牌覆盖。
由于棋盘是 2 k ∗ 2 k 2^k*2^k 2k∗2k的,很容易在中间横竖各一刀划分为4个 2 k − 1 ∗ 2 k − 1 2^{k-1}*2^{k-1} 2k−1∗2k−1的小棋盘,继续划分一直到k=1,成为 2 ∗ 2 2*2 2∗2的棋盘。如果k=1,且 2 ∗ 2 2*2 2∗2的棋盘上有一个黑色方块,那么可以用一块L牌覆盖。
那么其它的不含黑色方块的区域呢?当k=2时,棋盘大小为 4 × 4 4×4 4×4,其上下左右四个区域有一个区域有黑色方块,另外三个没有。那么我们可以用一块L牌覆盖有黑色方块的区域,另外三个区域采用下图的覆盖方式,能够留出一个L型的未覆盖区域,刚好再用一块L牌覆盖。
这样我们就知道递归的基本思路了:将棋盘划分成四部分,如果:
每次递归分别检查上下左右四部分,如果有黑色方块则继续递归,否则填充特殊方块。将特殊方块视为黑色方块并再次递归。当棋盘为 2 ∗ 2 2*2 2∗2时填充完毕,当棋盘为 1 ∗ 1 1*1 1∗1时直接返回(base case)。注意全局变量count和局部变量t的使用,count的最终值同时也是使用的L牌块数。
#include
#include
using namespace std;
int count = 1;
void print(vector<vector<int>> s)
{
for(int i = 0; i < s.size(); i++)
{
for(int j = 0; j < s[0].size(); j++)
cout<<s[i][j]<<", ";
cout<<endl;
}
}
void cover_board (vector< vector<int> > &board, int size, int lu_r, int lu_c, int black_r, int black_c) //black_r和black_c记录黑色方块所在行和列。lu_x和lu_y记录当前棋盘左上角的行和列。
{
if(size == 1) return;
int n = size / 2;
int t = count++;
if(black_r < lu_r + n && black_c < lu_c + n) //黑色方块在左上角
cover_board(board, n, lu_r, lu_c, black_r, black_c);
else {board[lu_r + n - 1][lu_c + n - 1] = t; cover_board(board, n, lu_r, lu_c, lu_r + n - 1, lu_c + n - 1);}
if(black_r >= lu_r + n && black_c < lu_c + n) //黑色方块在左下角
cover_board(board, n, lu_r + n, lu_c, black_r, black_c);
else {board[lu_r + n][lu_c + n - 1] = t; cover_board(board, n, lu_r+n, lu_c, lu_r + n, lu_c + n-1);}
if(black_r < lu_r+n && black_c >= lu_c + n) //黑色方块在右上角
cover_board(board, n, lu_r, lu_c+n, black_r, black_c);
else {board[lu_r + n - 1][lu_c + n] = t; cover_board(board, n, lu_r, lu_c+n, lu_r + n-1, lu_c + n);}
if(black_r >= lu_r+n && black_c >= lu_c + n) //黑色方块在右下角
cover_board(board, n, lu_r+n, lu_c+n, black_r, black_c);
else {board[lu_r + n][lu_c + n] = t; cover_board(board, n, lu_r+n, lu_c+n, lu_r + n, lu_c + n);}
}
int main()
{
int size=8;
vector<vector<int>> chess_board(size, vector<int> (size, 0));
int r=3, c=5;
cover_board(chess_board, size, 0, 0, r, c);
print(chess_board);
return 0;
}