棋盘覆盖问题
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;
}
一个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;
}
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Lua和C语言的交互详解
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C语言自动生成enum值和名字映射代码
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- C语言实现选择排序、冒泡排序和快速排序的代码示例
- 探讨C语言的那些小秘密之断言
- C语言实现BMP转换JPG的方法
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置