*昨天上传的代码,经过再次测试发现有问题,其中对边界、终止条件的判断都有错误。。。→_→,今天重新改正,对之前看过代码的童鞋表示sorry。。。(2017.5.13 16:24)*
问题描述:
在一个2^k×2^k (k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。显然,特殊方格在棋盘中可能出现的位置有4^k种,因而有4^k种不同的棋盘。棋盘覆盖问题(chess cover problem)要求使用4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
关于棋盘划分的更多概念请戳传送门:棋盘覆盖问题
实现如下:
class Solution
{
public:
int num = ;//累计计算
int **board = NULL;//动态二维数组指针
void printBoard(int **board, int row, int col)//输出函数
{
for (int i = ; i < row; ++i)
{
for (int j = ; j < col; ++j)
cout << setw() <<board[i][j];
cout << endl;
}
cout << endl;
}
void createBoard(int chessboardSize, int dr, int dc)//动态申请内存函数
{
board = (int **)malloc(chessboardSize * sizeof(int*));
assert(board != NULL);
for (int i = ; i < chessboardSize; ++i)
{
board[i] = (int*)malloc(chessboardSize * sizeof(int));
assert(board[i] != NULL);
memset(board[i], , sizeof(int)*chessboardSize);
}
board[dr][dc] = -;//将特殊点设置为-1
}
void freeBoard(int row)//释放动态内存空间,防止内存泄漏
{
for (int i = ; i < row; ++i)
free(board[i]);
free(board);
}
//chessboardSize表示此时范围的n*n,n的值
//dr表示特殊点的行下标
//dc表示特殊点的列下标
//tr表示此时范围的左上角在数组中的行下标
//tc表示此时范围的左上角在数组中的列下标
void Coverage(int chessboardSize, int dr, int dc, int tr, int tc)
{
if (chessboardSize == ) return;//当范围为1时,表示只有一个元素,return
int tmp = ++num;//每进入一个范围内,num累加
int s = chessboardSize / ;//获取此时范围内的下一个小范围的n大小
//判断特殊点是否在范围内的第一象限
if (dr < tr + s && dr >= && dc < tc + s && dc >= )
Coverage(s, dr, dc, tr, tc);
else//否则,将此第一象限的右下角设置为相对特殊点
{
board[tr + s - ][tc + s - ] = tmp;
Coverage(s, tr + s - , tc + s - , tr, tc);
}
//判断特殊点是否在范围内的第四象限
if (dr >= && dr < tr + s && dc >= tc + s && dc < tc + * s)
Coverage(s, dr, dc, tr, tc + s);
else//否则,将此第四象限的右下角设置为相对特殊点
{
board[tr + s - ][tc + s] = tmp;
Coverage(s, tr + s - , tc + s, tr, tc + s);
}
//判断特殊点是否在范围内的第二象限
if (dr >= tr + s && dr < tr + * s && dc >= && dc < tc + s)
Coverage(s, dr, dc, tr + s, tc);
else//否则,将此第二象限的右下角设置为相对特殊点
{
board[tr + s][tc + s - ] = tmp;
Coverage(s, tr + s, tc + s - , tr + s, tc);
}
//判断特殊点是否在范围内的第三象限
if (dr >= tr + s && dr < tr + * s && dc >= tc + s && dc < tc + * s)
Coverage(s, dr, dc, tr + s, tc + s);
else//否则,将此第三象限的右下角设置为相对特殊点
{
board[tr + s][tc + s] = tmp;
Coverage(s, tr + s, tc + s, tr + s, tc + s);
}
//printBoard(board, 8, 8);
}
void ChessboardCoverage(int chessboardSize, int dr, int dc)
{
if (chessboardSize < || dr < || dc < || dr >= chessboardSize || dc >= chessboardSize) return;//防御性动作
createBoard(chessboardSize, dr, dc);//动态生成二维数组
Coverage(chessboardSize, dr, dc, , );//开始覆盖
printBoard(board, chessboardSize, chessboardSize);//输出
freeBoard(chessboardSize);//释放动态空间
}
};
测试用例: