什么是棋盘覆盖问题?请看 —> 百度百科 - 棋盘覆盖问题
如何更好地显示算法结果?请看 —> 用QT设计《棋盘覆盖问题》UI部分
CCPalgorithm.hpp
#ifndef _CCP_ALGORITHM_
#define _CCP_ALGORITHM_
#include
// num为棋盘边长(单位:方格个数),I和J为特殊方格的位置。
// 该函数返回一个二维数组,二维数组包含了N+1组数,每组数表示一个L型骨牌。
std::vector<std::vector<int>> solve_problem(int num, int I, int J);
// 分治法的递归函数
void DC(std::vector<std::vector<int>>& result, // 表示棋盘的数组
int tlI, int tlJ, int brI, int brJ, // 当前管理的区域的top left及bottom right的位置
int spcI, int spcJ, // 特殊点的位置
int& n); // L型骨牌的编号
#endif
CCPalgorithm.cpp
std::vectorint>> solve_problem(int num, int I, int J)
{
// 创建棋盘
std::vectorint>> result(num, std::vector<int>(num, -1));
int n = 0;
result[I][J] = n; // 特殊点编号为0
DC(result, 0, 0, result.size() - 1, result[0].size() - 1, I, J, ++n);
return result;
}
void DC(std::vectorint>>& result,
int tlI, int tlJ, int brI, int brJ,
int spcI, int spcJ,
int& n)
{
if (brI - tlI <= 1) // 终止条件,区域为 2 * 2 大小时停止
{
/**** 对除特殊点外的三个方格统一编号为一个L型骨牌 ****/
int temp = result[spcI][spcJ];
result[tlI][tlJ] = n;
result[tlI + 1][tlJ] = n;
result[tlI][tlJ + 1] = n;
result[tlI + 1][tlJ + 1] = n;
result[spcI][spcJ] = temp;
/**** 对除特殊点外的三个方格统一编号为一个L型骨牌 ****/
++n;
return;
}
int midI = tlI + (brI- tlI) / 2;
int midJ = tlJ + (brJ- tlJ) / 2;
int tempN = n++;
/******************** 处理左上角区域 *******************/
if (midI >= spcI && midJ >= spcJ) // 如果特殊点在该区域
{
DC(result, tlI, tlJ, midI, midJ, spcI, spcJ, n);
}
else
{
// 如果特殊点不在此区域,把此区域的右下角标记为特殊点递归处理
result[midI][midJ] = tempN;
DC(result, tlI, tlJ, midI, midJ, midI, midJ, n);
}
/****************** 处理左上角区域END ******************/
/******************** 处理右上角区域 *******************/
if (midI >= spcI && midJ < spcJ)
{
DC(result, tlI, midJ + 1, midI, brJ, spcI, spcJ, n);
}
else
{
result[midI][midJ + 1] = tempN;
DC(result, tlI, midJ + 1, midI, brJ, midI, midJ + 1, n);
}
/****************** 处理右上角区域END ******************/
/******************** 处理左下角区域 *******************/
if (midI < spcI && midJ >= spcJ)
{
DC(result, midI + 1, tlJ, brI, midJ, spcI, spcJ, n);
}
else
{
result[midI + 1][midJ] = tempN;
DC(result, midI + 1, tlJ, brI, midJ, midI + 1, midJ, n);
}
/****************** 处理左下角区域END ******************/
/******************** 处理右下角区域 *******************/
if (midI < spcI && midJ < spcJ)
{
DC(result, midI + 1, midJ + 1, brI, brJ, spcI, spcJ, n);
}
else
{
result[midI + 1][midJ + 1] = tempN;
DC(result, midI + 1, midJ + 1, brI, brJ, midI + 1, midJ + 1, n);
}
/******************* 处理右下角区域END *****************/
}