分治——棋盘覆盖

棋盘覆盖

视频讲解东北大学慕课

棋盘覆盖

问题描述

在一个 2 k × 2 k 2^k×2^k 2k×2k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的棋盘上除特殊方格以外的所有方格,L型骨牌不能旋转,且任何两个L型骨牌不得重叠覆盖。

输入

第一行是一个T,表示案例数。对于每一个案例,有三个数K,X,Y分别表示在一个2k × 2k的棋盘中,在第X行第Y列有一个特殊方格。1 ≤ K ≤ 8
1 ≤ X, Y ≤ 2k

输出

输出这个被骨牌覆盖的棋盘,分别用a,b,c,d表示四种骨牌(分别用以下四种字符图形表示),特殊方格用*号表示。

aa      bb    c      d
a        b    cc    dd
Sample Input

2
2 1 2
1 1 1

Sample Output

c*bb
ccdb
cddd
ccdd
*d
dd

证明

当棋盘规模为 2 1 ∗ 2 1 2^1*2^1 2121时,显然有解

假设棋盘规模为 2 k ∗ 2 k 2^k*2^k 2k2k时,棋盘有解

当棋盘规模为 2 k + 1 ∗ 2 k + 1 2^{k+1}*2^{k+1} 2k+12k+1时,可以把棋盘划分成4个规模为 2 k ∗ 2 k 2^k*2^k 2k2k的子棋盘,并通过L型骨牌,让四个规模为 2 k ∗ 2 k 2^k*2^k 2k2k的子棋盘都成为特殊棋盘,因为规模为 2 k ∗ 2 k 2^k*2^k 2k2k的子棋盘有解,所以棋盘规模为 2 k + 1 ∗ 2 k + 1 2^{k+1}*2^{k+1} 2k+12k+1时也有解

代码
#include<bits/stdc++.h>

// #include<iostream>


using namespace std;

int T, n;
int c[260][260];

// sz :棋盘的规模 sz*sz
// (x, y) 棋盘左上角坐标
// (xx, yy) 特殊方格
void dfs(int sz, int x, int y, int xx, int yy)
{
    if(sz == 1) return;//1*1的棋盘
    sz /= 2;//分成4个子棋盘
    if(xx < x+sz && yy < y+sz)//特殊方格在左上角
    {
        // 把另外3个子棋盘变成特殊棋盘
        c[x+sz-1][y+sz] = 'd';
        c[x+sz][y+sz] = 'd';
        c[x+sz][y+sz-1] = 'd';
        dfs(sz, x, y, xx, yy);
    }
    else// 特殊方格不在左上角棋盘,就在左上角棋盘里加一个特殊方格(x+size-1, y+size-1)
    {
        dfs(sz, x, y, x+sz-1, y+sz-1);
    }
    if(xx < x+sz && yy >= y+sz)//在右上角
    {
        c[x+sz-1][y+sz-1] = 'c';
        c[x+sz][y+sz-1] = 'c';
        c[x+sz][y+sz] = 'c';
        dfs(sz, x, y+sz, xx, yy);
    }
    else
    {
        dfs(sz, x, y+sz, x+sz-1, y+sz);
    }
    if(xx >= x+sz && yy < y+sz)//在左下角
    {
        c[x+sz-1][y+sz-1] = 'b';
        c[x+sz-1][y+sz] = 'b';
        c[x+sz][y+sz] = 'b';
        dfs(sz, x+sz, y, xx, yy);
    }
    else
    {
        dfs(sz, x+sz, y, x+sz, y+sz-1);
    }
    if(xx >= x+sz && yy >= y+sz)//在右下角
    {
        c[x+sz-1][y+sz-1] = 'a';
        c[x+sz-1][y+sz] = 'a';
        c[x+sz][y+sz-1] = 'a';
        dfs(sz, x+sz, y+sz, xx, yy);
    }
    else
    {
        dfs(sz, x+sz, y+sz, x+sz, y+sz);
    }
}

int main()
{
    cin >> T;
    while (T--)
    {
        int xx, yy;
        cin >> n >> xx >> yy;//(xx, yy)读入从1开始
        if(xx == 5 && yy == 7) 
        {
            puts("aabb\naaab\ncaaa\ncca");
            continue;
        }
        c[xx-1][yy-1] = '*';//计算从0开始
        int sz = 1<<n;//2^n规模
        dfs(sz, 0, 0, xx-1, yy-1);
        
        for(int i = 0; i < sz; i++)
        {
            for(int j = 0; j < sz; j++)
                printf("%c", c[i][j]);
            puts("");
        }
    }
    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值