棋盘覆盖问题

来源:互联网 发布:软件研发的特点 编辑:程序博客网 时间:2024/05/22 05:24

棋盘覆盖问题是在一个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;}



0 0
原创粉丝点击