棋盘覆盖超详细解析+代码实现-分治法解决

棋盘覆盖

最近算法oj作业
参考代码。我以16*16的方格为例子,一步一步来。期望能够共同进步!
原理什么的,可以看其他文章。

一、问题描述

题目描述
在一个2^k * 2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
在这里插入图片描述
输入要求
输入一个整数k,k<=5;
输入特殊格子的坐标x,y。

输出要求
输出一个由数值表示的二维矩阵。填充规则如下:
(1)用数值填充方格;
(2)特殊方格数值为0;
(3)从中心点开始;然后左上、右上、左下、右下的计数顺序填数;同一块用相同数值表示;
(4)每个数值占4个位置空间;右对齐,左补空格。

输入样例
3
1 2

输出样例
3 3 4 4 8 8 9 9
3 2 0 4 8 7 7 9
5 2 2 6 10 10 7 11
5 5 6 6 1 10 11 11
13 13 14 1 1 18 19 19
13 12 14 14 18 18 17 19
15 12 12 16 20 17 17 21
15 15 16 16 20 20 21 21

二、详细解析

1.首先假设特殊格子在(5,5)点。

在这里插入图片描述

2.第一步能就是将其分为4部分,其实也就是16/2*16/2的方格,就可以得到。

如图中红线所示
在这里插入图片描述

3.关键的来了!再分为四部分之后,查看这四部分是否还有特殊子。没有的分别加上,让其含有,然后再划分子问题。以这个为例子,右上,左下,右下没有,那么分别再他们的对角加上。

在这里插入图片描述

5.这样四个部分 分别含有特殊子,四个部分递归,进行问题分解。

如图中蓝线所示。
在这里插入图片描述
继续。
在这里插入图片描述
6.以左上部分为例子,递归求解 分成了四部分,不含有特殊的对角加上,继续对这左上的四部分递归。

如橙色线所示
在这里插入图片描述
在这里插入图片描述
7.最后橙色线的格子里都含有特殊子了,那么都填充起来就OK了。

三、代码实现

代码:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int number=0;
int Board[33][33];
//tr,tc是方格左上角的位置,dr,dc是特殊方格的位置
void ChessBoard(int tr,int tc,int dr,int dc,int size)
{
    if(size==1)
        return;
    int ind=++number;//骨牌的编号
    int s=size/2;//将棋盘分割为4个子问题,即行和列各取一半

    if(dr<tr+s && dc<tc+s)//当特殊格子在左上的子问题中
        ChessBoard(tr,tc,dr,dc,s);
    else//如果特殊格子不在左上时,将左上的右下角标记为黑格
    {
        Board[tr+s-1][tc+s-1]=ind;//用编号为ind的骨牌覆盖该子问题中的右下角
        ChessBoard(tr,tc,tr+s-1,tc+s-1,s);//继续覆盖其余格子
    }

    if(dr<tr+s && dc>=tc+s)//当特殊格子在右上的子问题中
        ChessBoard(tr,tc+s,dr,dc,s);
    else//如果特殊格子不在右上,将右上的左下角标记为黑格
    {
        Board[tr+s-1][tc+s]=ind;
        ChessBoard(tr,tc+s,tr+s-1,tc+s,s);
    }

    if(dr>=tr+s && dc<tc+s)//当特殊格子在左下的子问题中
        ChessBoard(tr+s,tc,dr,dc,s);
    else//如果特殊格子不在左下时,将左下的右上角标记为黑格
    {
        Board[tr+s][tc+s-1]=ind;
        ChessBoard(tr+s,tc,tr+s,tc+s-1,s);
    }

    if(dr>=tr+s && dc>=tc+s)//当特殊格子在右下的子问题中
        ChessBoard(tr+s,tc+s,dr,dc,s);
    else//如果特殊格子不在右下时,将右下的左上角标记为黑格
    {
        Board[tr+s][tc+s]=ind;
        ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
    }

}
int main()
{
    int k,x,y;
    scanf("%d",&k);
    int size=pow(2,k);
    scanf("%d%d",&x,&y);
    ChessBoard(0,0,x,y,size);
    for(int i=0;i<size;i++)
        {
            for(int j=0;j<size;j++)
            {
                printf("%4d",Board[i][j]);
            }
            printf("\n");
        }
    return 0;
}



版权声明:本文为jnbfknasf113原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。