您的位置:首页 > 编程语言 > C语言/C++

棋盘覆盖问题

2016-04-24 11:48 525 查看
棋盘覆盖问题是在一个2^k*2^k(k>=0)个方格组成的棋盘中,用L型骨牌覆盖覆盖棋盘上除特殊方格以外的所有方格,并且任何两个L型骨牌不可以重叠覆盖。L型骨牌可以有如下4种形态:



一个L型骨牌由3个方格组成,所以覆盖一个棋盘需要(2^k*2^k-1)/3个L型骨牌。

棋盘覆盖问题采用的的是分治法的思想:将1个大的棋盘分成4个小的棋盘,特殊方格一定在4个小棋盘中的某一个棋盘中,其余3个则没有特殊方格。接下就是要将3个没有特殊方格的棋盘变成有特殊方格的棋盘,因为3个棋盘的汇合处必定可以构成一个L型骨牌,此时就用一个L型骨牌来覆盖这3个方格(即其余3个没有特殊方格的子棋盘的汇合处),如图所示:



图上红色标记的为特殊方格所在的位置,蓝色为用一个L型骨牌覆盖剩下没有特殊方格的3个子棋盘,这样3个子棋盘就成为有特殊方格的棋盘。从而将原问题转化为4个较小规模的棋盘覆盖问题。继续递归地这样分割,直到棋盘成为1*1的棋盘。

代码实现如下:

#include <cstdio>
using namespace std;
const int size=8;
int a[size][size];
int tile;
void chessBoard(int tr,int tc,int dr,int dc,int s){
if(s==1){
return;
}
int t = ++tile;
s = s/2;
//覆盖左上角的棋盘
if(dr<tr+s&&dc<tc+s){
//特殊方格在左上角棋盘中
chessBoard(tr,tc,dr,dc,s);
}else{
//覆盖左上角棋盘中右下角的方格
a[tr+s-1][tc+s-1]=t;
//覆盖左上角棋盘中的其余方格
chessBoard(tr,tc,tr+s-1,tc+s-1,s);
}
//覆盖右上角的棋盘
if(dr<tr+s&&dc>=tc+s){
chessBoard(tr,tc+s,dr,dc,s);
}else{
a[tr+s-1][tc+s]=t;
chessBoard(tr,tc+s,tr+s-1,tc+s,s);
}
//覆盖左下角的棋盘
if(dr>=tr+s&&dc<tc+s){
chessBoard(tr+s,tc,dr,dc,s);
}else{
a[tr+s][tc+s-1]=t;
chessBoard(tr+s,tc,tr+s,tr+s-1,s);
}
//覆盖右下角的棋盘
if(dr>=tr+s&&dc>=tc+s){
chessBoard(tr+s,tc+s,dr,dc,s);
}else{
a[tr+s][tc+s]=t;
chessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}

int main()
{
int tr=0,tc=0,dr,dc,s;//size为棋盘的大小,dr、dc分别为特殊方格的位置
printf("请输入特殊方格的位置:\n");
scanf("%d%d",&dr,&dc);
tile=0;
s=size;
a[dr][dc] = tile;//特殊方格用0标记
chessBoard(tr,tc,dr,dc,s);
//输出数组a
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
printf("%d\t",a[i][j]);
}
printf("\n");
}
printf("所用L型骨牌的个数为:%d\n",tile);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息