【分治】问题8.3.1 棋盘覆盖问题

算法竞赛入门 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;
}








  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值