问题8.3.1 棋盘覆盖问题(分治)

来源:互联网 发布:淘宝女装店 编辑:程序博客网 时间:2024/06/15 17:20

算法竞赛入门 LRJ 棋盘覆盖问题

在一个 2^k * 2^k 个方格组成的棋盘中,若恰有一个方格与其它方格不同,则称该方格为一特殊方格,称该棋盘为一特殊棋盘。显然特殊方格在棋盘上出现的位置有 4^k 种情形。因而对任何 k>=0 ,有 4^k 种不同的特殊棋盘。下图所示的特殊棋盘为 k=2 时 16 个特殊棋盘中的一个。

 

     在棋盘覆盖问题中,要用下图中 4 中不同形态的 L 型骨牌覆盖一个给定的特殊棋牌上除特殊方格以外的所有方格,且任何 2 个 L 型骨牌不得重叠覆盖。易知,在任何一个 2^k * 2^k 的棋盘中,用到的 L 型骨牌个数恰为 (4^k-1)/3 。现给出棋盘的大小和特殊方格所在的位置,请找出这种棋盘。


【样例输入】

     1

     0 0

【样例输出】

     0 1

     1 1

题解: 2^k * 2^k 的棋盘分割成4个 2^(k-1) * 2^(k-1) 的小棋盘,分别在左上,右上,左下,右下。判断特殊方格所在的小棋盘,在没有特殊方格的小棋盘做如下处理:

左上小棋盘: 在其右下角填一个特殊方格。

右上小棋盘: 在其左下角填一个特殊方格。

左下小棋盘: 在其右上角填一个特殊方格。

右下小棋盘: 在其左上角填一个特殊方格。

没有特殊方格的三个小棋盘填方格后,其就相当于填一个L骨牌。

那么在四个小棋盘中都有一个特殊方格,问题缩小为:在2^(k-1) * 2^(k-1) 的小棋盘填L骨牌。

由而分治处理。


#include<iostream>#include<cstdio>#include<cstring>#include<stack>#include<map>#include<queue>#include<cmath>#include<algorithm>#include<deque>typedef long long LL;using namespace std;#pragma comment(linker, "/STACK:102400000,102400000")const int INF=0x3f3f3f3f;const int N = 110;int board[N][N];int type; // L骨牌的编号void init(){    memset(board,0,sizeof(board));    type = 1;}// br bc 棋盘左上角位置// x y 特殊方格位置void slove(int br,int bc,int x,int y,int Size){    if(Size == 1)        return ;    int s = Size/2;    int t = type++;    // 处理左上    if(br+s > x && bc+s > y)    //有特殊方格        slove(br,bc,x,y,s);    else                        //没有特殊方格    {        board[br+s-1][bc+s-1] = t;        slove(br,bc,br+s-1,bc+s-1,s);    }    // 处理右上    if(br+s > x && bc+s <= y)    //有特殊方格        slove(br,bc+s,x,y,s);    else                        //没有特殊方格    {        board[br+s-1][bc+s] = t;        slove(br,bc+s,br+s-1,bc+s,s);    }    // 处理左下    if(br+s <= x && bc+s > y)    //有特殊方格        slove(br+s,bc,x,y,s);    else                        //没有特殊方格    {        board[br+s][bc+s-1] = t;        slove(br+s,bc,br+s,bc+s-1,s);    }    // 处理右下    if(br+s <= x && bc+s <= y)    //有特殊方格        slove(br+s,bc+s,x,y,s);    else                        //没有特殊方格    {        board[br+s][bc+s] = t;        slove(br+s,bc+s,br+s,bc+s,s);    }}int main(){    init();    int k,x,y;    scanf("%d",&k);    int Size = 1<<k;    //x , y 特殊方格的位置    scanf("%d%d",&x,&y);    slove(0,0,x,y,Size);    for(int i = 0; i < Size; i++)    {        for(int j = 0; j < Size; j++)            printf("%d ",board[i][j]);        printf("\n");    }    return 0;}








0 0
原创粉丝点击