算法设计与分析——棋盘覆盖问题

棋盘覆盖问题

什么是棋盘覆盖问题

关于这个,百度一下,你就知道,本文主要介绍棋盘覆盖问题的思路

求解思路

  • 对于一个给定的 2 k ∗ 2 k 2^{k}*2^{k} 2k2k的特殊棋盘,假设其特殊方格(蓝色部分)如下图所示。
    在这里插入图片描述
    若再在中央位置放入一个L形骨牌,则将其由中央十字分出的四个部分子棋盘(A、B、C、D),变成了特殊棋盘(如下图),其被分为了4个特殊棋盘
    在这里插入图片描述

欲将其如此分为四个特殊棋盘,该L型骨牌的形状需要满足:对于该L型骨牌所在的三块方格(可视为特殊方格),每个方格所在的子棋盘没有任何其它特殊方格,以这样的方式在中央放入L形骨牌,则可将一个特殊棋盘划分为4个子特殊棋盘,如此对每个子特殊棋盘进行同样的划分操作,依次递归,在棋盘只有一个方块时直接返回。如此,用L型骨牌覆盖了整个棋盘。

代码

#include <iostream>
#include <string.h>

using namespace std;
typedef long long ll;
ll pansize,xa,ya; //棋盘边长,特殊方格的位置坐标
ll qipan[10000][10000];
ll num=0;//已放入L形骨牌的数量

// stx,sty:棋盘最左上角方格坐标、xa,ya:特殊方格坐标
void Cover(ll stx,ll sty,ll pansize,ll xa,ll ya)
{
    if(pansize==1)
    {
        return;
    }
    ll len=pansize/2;// 子棋盘的宽度
    ++num;//在中央放入L形骨牌,分解为四个特殊子棋盘
    if(xa<stx+len&&ya<sty+len)
    {
        qipan[stx+len][sty+len-1]=num;
        qipan[stx+len][sty+len]=num;
        qipan[stx+len-1][sty+len]=num;
        Cover(stx,sty,len,xa,ya);
        Cover(stx+len,sty,len,stx+len,sty+len-1);
        Cover(stx+len,sty+len,len,stx+len,sty+len);
        Cover(stx,sty+len,len,stx+len-1,sty+len);
    }
    if(xa>=stx+len&&ya<sty+len)
    {
        qipan[stx+len-1][sty+len-1]=num;
        qipan[stx+len-1][sty+len]=num;
        qipan[stx+len][sty+len]=num;
        Cover(stx,sty,len,stx+len-1,sty+len-1);
        Cover(stx+len,sty,len,xa,ya);
        Cover(stx+len,sty+len,len,stx+len,sty+len);
        Cover(stx,sty+len,len,stx+len-1,sty+len);
    }

    if(xa>=stx+len&&ya>=sty+len)
    {
        qipan[stx+len-1][sty+len-1]=num;
        qipan[stx+len][sty+len-1]=num;
        qipan[stx+len-1][sty+len]=num;
        Cover(stx,sty,len,stx+len-1,sty+len-1);
        Cover(stx+len,sty,len,stx+len,sty+len-1);
        Cover(stx+len,sty+len,len,xa,ya);
        Cover(stx,sty+len,len,stx+len-1,sty+len);
    }
    if(xa<stx+len&&ya>=sty+len)
    {
        qipan[stx+len-1][sty+len-1]=num;
        qipan[stx+len][sty+len-1]=num;
        qipan[stx+len][sty+len]=num;
        Cover(stx,sty,len,stx+len-1,sty+len-1);
        Cover(stx+len,sty,len,stx+len,sty+len-1);
        Cover(stx+len,sty+len,len,stx+len,sty+len);
        Cover(stx,sty+len,len,xa,ya);
    }


}

int main()
{
    memset(qipan,0,10000*10000*sizeof(ll));
    printf("棋盘边长:");
    scanf("%lld",&pansize);
    printf("特殊方格位置:");//坐标从0开始
    scanf("%lld%lld",&xa,&ya);
    printf("覆盖结果:\n");
    Cover(0,0,pansize,xa,ya);
    for(ll i1=0;i1<pansize;++i1)
    {
        for(ll i2=0;i2<pansize;++i2)
        {
            if(i2!=pansize-1)
            {
                printf("%lld ",qipan[i1][i2]);
            }
            else
            {
                printf("%lld\n",qipan[i1][i2]);
            }
        }
    }
    return 0;
}

算法运行截图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

long_red

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值