题目描述
用4种不同形态的L型骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。输入数据由程序运行后的界面中的编辑框中输入游戏规模,特殊方格的位置。将覆盖的结果在窗口中显示出来。
解题思路
有特殊方格----覆盖其他方格
无特殊方格----构造特殊方格----覆盖其他方格
(1)棋盘有以下参数:
--棋盘大小2k×2k
--棋盘边长为s=2k-1
--棋盘顶点坐标 (tr,tc) [初始值一般为(0,0)]
--特殊方格坐标 (dr,tc)
[注:棋盘大小在输入时可以有两种方式,一种是直接输入2k,此时需要输入的数值需为2的次方数,如2,4,8。另外一种方式是直接输入k,最好在输入时注明。]
(2)将棋盘均分为四块,并划分区域(顺序可自行调整)
①如何判断区域内是否含有特殊方格?
A区:dr<tr+s && dc<tc+s;
B区:dr>=tr+s && dc<tc+s;
C区:dr<tr+s && dc>=tc+s;
D区:dr>=tr+s && dc>=tc+s;
②如果区域内没有特殊方格,如何构造特殊方格?
A区:特殊方格坐标 (tr+s-1,tc+s-1) ;
B区:特殊方格坐标 (tr + s ,tc+s-1) ;
C区:特殊方格坐标 (tr+s-1,tc + s ) ;
D区:特殊方格坐标 (tr + s ,tc + s ) ;
③递归出口在哪里?
当s==1时,即棋盘无法再分割,即为递归出口。
代码实现
#include<iostream> //小王的代码
using namespace std; //命名空间
int cnt=1;
int Board[100][100];
void qpfg(int tr,int tc,int dr,int dc,int size) //棋盘覆盖函数
{
if(size==1) return; //如果棋盘无法再划分,返回
int s=size/2; //设置有棋盘一半大小的中间变量
int t=cnt++; //定义计数器
if(dr<tr+s && dc<tc+s) //如果特殊方格在此棋盘中
qpfg(tr,tc,dr,dc,s); //覆盖其他方格
else //如果特殊方格不在此棋盘中
{
Board[tr+s-1][tc+s-1]=t; //构造特殊方格
qpfg(tr,tc,tr+s-1,tc+s-1,s);//覆盖其他方格
}
if(dr>=tr+s && dc<tc+s) //如果特殊方格在此棋盘中
qpfg(tr+s,tc,dr,dc,s); //覆盖其他方格
else //如果特殊方格不在此棋盘中
{
Board[tr+s][tc+s-1]=t; //构造特殊方格
qpfg(tr+s,tc,tr+s,tc+s-1,s);//覆盖其他方格
}
if(dr<tr+s && dc>=tc+s) //如果特殊方格在此棋盘中
qpfg(tr,tc+s,dr,dc,s); //覆盖其他方格
else //如果特殊方格不在此棋盘中
{
Board[tr+s-1][tc+s]=t; //构造特殊方格
qpfg(tr,tc+s,tr+s-1,tc+s,s);//覆盖其他方格
}
if(dr>=tr+s && dc>=tc+s) //如果特殊方格在此棋盘中
qpfg(tr+s,tc+s,dr,dc,s); //覆盖其他方格
else //如果特殊方格不在此棋盘中
{
Board[tr+s][tc+s]=t; //构造特殊方格
qpfg(tr+s,tc+s,tr+s,tc+s,s);//覆盖其他方格
}
}
int main()
{
int dr,dc,n; //定义特殊方格横纵坐标、棋盘大小
cout<<"请输入棋盘大小:";
cin>>n; //n的值不用为2的次幂
int size=1;
for(int a=1;a<=n;a++) //size的值为2的n次幂
size*=2;
cout<<endl;
cout<<"请输入特殊方格的位置:";
cin>>dr>>dc;
cout<<endl;
cout<<"您的棋盘为:"<<endl;
qpfg(0,0,dr,dc,size); //调用函数时直接给tc和tr赋值0
for(int i=0;i<size;i++) //输出二维数组(即整个棋盘)
{
for(int j=0;j<size;j++)
cout<<Board[i][j]<<'\t';//'\t'可保证输出整齐
cout<<endl;
}
return 0;
}
—关于棋盘覆盖算法的几点思考:
(1)对于使用递归算法求解的问题,我们只需找到递归通式和递归出口,千万不要试图层层追踪。
(2)有关 t 的取值问题:t 在程序中只有增值,没有减值,即 t 只会从 1 开始增加,但为什么在最大的划分区域中,构造的特殊方格值均为 1 ?
——在函数递归的退回过程中,可能要执行某些动作,包括回复在前行过程中存储起来的某些数据。