棋盘覆盖问题(递归与分治,紫书P229)

在一个 2^k * 2^k 个方格组成的棋盘中,若恰有一个方格与其它方格不同,则称该方格为一特殊方格(黑色方格),称该棋盘为一特殊棋盘。显然特殊方格在棋盘上出现的位置有 4^k 种情形。因而对任何 k>=0 ,有 4^k 种不同的特殊棋盘。下图所示的特殊棋盘为 k=2 时 16 个特殊棋盘中的一个。

《棋盘覆盖问题(递归与分治,紫书P229)》

在棋盘覆盖问题中,要用下图中 4 中不同形态的 L 型骨牌覆盖一个给定的特殊棋牌上除特殊方格以外的所有方格,且任何 2 个 L 型骨牌不得重叠覆盖。易知,在任何一个 2^k * 2^k 的棋盘中,用到的 L 型骨牌个数恰为 (4^k-1)/3《棋盘覆盖问题(递归与分治,紫书P229)》 (这个地方大家也可以下去算一下,笔者再者提示一下,要用到数学里边的二项分布,当然你如果你够聪明《棋盘覆盖问题(递归与分治,紫书P229)》《棋盘覆盖问题(递归与分治,紫书P229)》,也可以直接观察《棋盘覆盖问题(递归与分治,紫书P229)》)。

《棋盘覆盖问题(递归与分治,紫书P229)》

用分治策略,可以设计解棋盘问题的一个简捷的算法。
当 k>0 时,将 2^k * 2^k 棋盘分割为 4 个 2^(k-1) * 2^(k-1) 子棋盘,如下图所示。

《棋盘覆盖问题(递归与分治,紫书P229)》

特殊方格必位于 4 个较小子棋盘之一中,其余 3 个子棋盘中无特殊方格。为了将这 3 个无特殊方格的子棋盘转化为特殊棋盘,我们可以用一个 L 型骨牌覆盖这 3 个较小的棋盘的汇合处,如下图所示,这 3 个子棋盘上被 L 型骨牌覆盖的方格就成为该棋盘上的特殊方格,从而将原问题化为 4 个较小规模的棋盘覆盖问题。递归的使用 这种分割,直至棋盘简化为 1×1 棋盘,也就是说当他的size为1的时候直接return;。

注意:题目要求的是什么?要求的是吧那个符合要求的整个表格打印出来,就是把整个表格里边哪里用到了L型,怎么用的都要标记出来

《棋盘覆盖问题(递归与分治,紫书P229)》

我的这个代码打印出来的实例,如输入size=4,row=2,col=3;

《棋盘覆盖问题(递归与分治,紫书P229)》

说句题外话,大家也不要见怪,为什么我的系统是XP《棋盘覆盖问题(递归与分治,紫书P229)》《棋盘覆盖问题(递归与分治,紫书P229)》,说句实话,这个不重要《棋盘覆盖问题(递归与分治,紫书P229)》

下边来看看我的代码:

#include <stdio.h>
#include <stdlib.h>

#include<string.h>
int nCount = 0;//用于记录每一个L型的编号,最大是多少就代表总共用到了多少个L
int Matrix[100][100];//将最后的结果打成表格
void chessBoard(int tr, int tc, int dr, int dc, int size);
int main()
{
    int size,r,c,row,col;
    memset(Matrix,0,sizeof(Matrix));
    scanf(“%d”,&size);//代表这整个方格的规模,就是size行,size列
    scanf(“%d%d”,&row,&col);//代表那个黑色方格的坐标
    chessBoard(0,0,row,col,size);//开始递归了
    for (r = 0; r < size; r++)
    {
        for (c = 0; c < size; c++)
        {
            printf(“%2d “,Matrix[r][c]);
        }
        printf(“\n”);
    }
    return 0;
}
void chessBoard(int tr, int tc, int dr, int dc, int size)
    int s,t;
    if (1 == size) return;
    s = size/2; //The number of grid the matrix’s edge
    t = ++ nCount;
    //locate the special  grid on bottom right corner
    if (dr < tr + s && dc < tc +s)//如果黑色方格就在指定的左上方的大方格里边就继续递归分治
    {
        chessBoard(tr,tc,dr,dc,s);
    }
    else//如果没有找到,也就是说那个黑色方格并不在左上方,那么就在左上方的大方格内部的右下方中填上数据,做标记
        //昨晚标记后继续在左上方递归分治
    {
        Matrix[tr+s-1][tc+s-1] = t;
        chessBoard(tr,tc,tr+s-1,tc+s-1,s);
    }

    //locate the special  grid on bottom left corner
    if (dr < tr + s && dc >= tc + s )//如果发现黑色方格在右上方就在右上方的大方格内继续递归
    {
        chessBoard(tr,tc+s,dr,dc,s);
    }
    else//就说明黑色方格不在右上方,那么就在右上方的大方格里边的左下方做标记,昨晚标记后继续在右上方递给分治
    {
        Matrix[tr+s-1][tc+s] = t;
        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
    {
        Matrix[tr+s][tc+s-1] = t;
        chessBoard(tr+s,tc,tr+s,tc+s-1,s);
    }
    //locate the special  grid on top left corner
    if (dr >= tr + s && dc >= tc + s)
    {
        chessBoard(tr+s,tc+s,dr,dc,s);
    }
    else
    {
        Matrix[tr+s][tc+s] = t;
        chessBoard(tr+s,tc+s,tr+s,tc+s,s);
    }
}

    原文作者:递归与分治算法
    原文地址: https://blog.csdn.net/wangjianbing1998/article/details/52088868
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞