7-1棋盘覆盖

作者 严华云

单位 湖州师范学院

在一个2k∗2k(k为正整数,k<=10,length=2k)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格(其坐标为a,b,分别代表行坐标号和列坐标号),以及有四种L型骨牌(如下图)。求用若干块这种L型骨牌实现除该特殊点棋盘的全覆盖。(本题要求采用分治算法做)

棋盘.png

输入格式:

输入三个数,分别是a,b,length.

输出格式:

输出整个棋盘。其中特殊方格填为0,然后铺棋盘的顺序为:先铺四个子棋盘交界的部分,然后递归的对每个子棋盘按照左上,右上,右下,左下的顺时针顺序铺满棋盘。每一块骨牌中三个方格数字相同,按照顺序标号,即第一块骨牌全标为1,第二块骨牌全标为2,...,以此类推。输出的每个数占4个场宽,右对齐。

输入样例:

1 1 4

表示:特殊格子为(1,1),棋盘有4行4列。

输出样例:

   0   2   3   3
   2   2   1   3
   5   1   1   4
   5   5   4   4

提示:先铺三个1,再铺三个2,...,最后铺三个5(即先处理子问题交界的地方,再处理左上,右上,右下,左下的子问题).

AC代码:

#include<bits/stdc++.h>
using namespace std;
int mp[1050][1050];
int a, b, length;
int cnt = 1;
int posc(int x, int y, int len,int mx,int my)//按照左上,右上,右下,左下的顺时针顺序划分区域 1,2,3,4
{
	  int cx = mx+len/2-1;//定位点必然点在1号区域 
      int cy = my+len/2-1;	
      if(x<=cx&&y<=cy) return 1;
      if(x<=cx&&y>cy) return 2;
      if(x>cx&&y>cy) return 3;
      if(x>cx&&y<=cy) return 4;
}
void dis(int x, int y,int len,int mx,int my)//x,y是障碍点,len是当前维护矩阵的边长,mx,my是当前维护的矩阵的左上角一点
{                                           //不论是x,y还是mx,my都是之于原始矩阵(最大的那个)所给出的坐标
   
    if (len <= 1) return;
    int cx = mx+len/2-1;
    int cy = my+len/2-1;//定位点是当前维护矩阵的中心点
    int wh = posc(x, y, len,mx,my);
    //cout << len << ":" <<"定位点:"<<cx << " " << cy <<" 障碍点"<<x<<" "<<y<<" wh:"<<wh<< endl;
    if (wh == 1)
    {
    	
        //1.
        mp[cx][cy + 1] = cnt;
        mp[cx + 1][cy + 1] = cnt;
        mp[cx + 1][cy] = cnt;
        cnt++;
        dis(x, y, len / 2,mx+0,my+0);
        dis(cx, cy + 1, len / 2,mx+0,my+len/2);
        dis(cx + 1, cy + 1, len / 2,mx+len/2,my+len/2);
        dis(cx + 1, cy, len / 2,mx+len/2,my+0);
    }
    
    else if (wh == 2)
    {
        mp[cx][cy] = cnt;
        //2.
        mp[cx + 1][cy + 1] = cnt;
        mp[cx + 1][cy] = cnt;
        cnt++;
        dis(cx, cy, len / 2,mx+0,my+0);
        dis(x, y, len / 2,mx+0,my+len/2);
        dis(cx + 1, cy + 1, len / 2,mx+len/2,my+len/2);
        dis(cx + 1, cy, len / 2,mx+len/2,my+0);
    }
    
    else if (wh == 3)
    {
        mp[cx][cy] = cnt;
        mp[cx][cy + 1] = cnt;
        //3.
        mp[cx + 1][cy] = cnt;
        cnt++;
        dis(cx, cy, len / 2,mx+0,my+0);
        dis(cx, cy + 1, len / 2,mx+0,my+len/2);
        dis(x, y, len / 2,mx+len/2,my+len/2);
        dis(cx + 1, cy, len / 2,mx+len/2,my+0);
    }
    
    else if (wh == 4)
    {
        mp[cx][cy] = cnt;
        mp[cx][cy + 1] = cnt;
        mp[cx + 1][cy + 1] = cnt;
        //4.
        cnt++;
        dis(cx, cy, len / 2,mx+0,my+0);
        dis(cx, cy + 1, len / 2,mx+0,my+len/2);
        dis(cx + 1, cy + 1, len / 2,mx+len/2,my+len/2);
        dis(x, y, len / 2,mx+len/2,my+0);
    }
}
int main()
{
    cin >> a >> b >> length;
    for (int i = 1; i <= length; i++)
        for (int j = 1; j <= length; j++)
            mp[i][j] = -1;
    mp[a][b] = 0;
    dis(a, b,length,1,1);
    for (int i = 1; i <= length; i++)
    {
        for (int j = 1; j <= length; j++)
        {
            printf("%4d",mp[i][j]);
        }
        cout << endl;
    }
    return 0;
}

把一个正方形分均分成大小一样的小正方形,按顺时针顺序标号1,2,3,4号区域

依据:判断特殊点(不可放置骨牌的点)在当前正方形的哪一号区域,然后选取缺角与之对应的L形骨牌放到正方形的中心,然后按顺序一直重复这个过程。

对选骨牌做出解释,以测试样例为例:(1,1)点位于1号区域,正好就选出了缺失一号区域这个角的骨牌。

仔细想一下,不论初始的a,b点在哪,都只对应唯一种可行的覆盖方案,即唯一解。ps反正我是画不出来:)

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值