棋盘覆盖问题

Description

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

Input

输入一个整数k,k<=5;
输入特殊格子的坐标x,y。

Output

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

分析:
函数的主干是四个if else循环,也就是说只会执行一个if中的语句,但是会执行3个else中的语句,这3个else中的语句就是构造不可覆盖格子,然后对含有新构造的不可覆盖点的子棋盘来重写进行棋盘覆盖,也就是递归调用棋盘覆盖函数,递归的结束条件就是子棋盘只有一个格子,也就是s=1,每次调用棋盘覆盖函数,都要进行s=size/2,目的就是把一个大棋盘划分为四个相同大小的子棋盘。

#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;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值