棋盘覆盖问题

一:问题描述

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

棋盘覆盖问题_第1张图片

      在棋盘覆盖问题中,要用下图中4中不同形态的L型骨牌覆盖一个给定的特殊棋牌上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。易知,在任何一个2^k * 2^k的棋盘中,用到的L型骨牌个数恰为(4^k-1)/3。

2

      用分治策略,可以设计解棋盘问题的一个简捷的算法。

      当k>0时,将2^k * 2^k棋盘分割为4个2^(k-1) * 2^(k-1)子棋盘,如下图所示。

棋盘覆盖问题_第2张图片

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

棋盘覆盖问题_第3张图片

 

 



#include<iostream>
using namespace std;
int board[100][100];
int time1=0;
void chessboard(int r1,int c1,int r2,int c2,int size)
{
    if(size==1)return ;
    int t=++time1;
    int s=size/2;//记录棋盘的大小
    //upleft
    if(r2<r1+s&&c2<c1+s)//判断是不是再左上方部分
    {
        chessboard(r1,c1,r2,c2,s);
    }
    else
    {
        board[r1+s-1][c1+s-1]=t;
        chessboard(r1,c1,r1+s-1,c1+s-1,s);
    }
    //upright
    if(r2<r1+s&&c2>=c1+s)//判断是不是再右上方部分
    {
        chessboard(r1,c1+s,r2,c2,s);
    }
    else
    {
        board[r1+s-1][c1+s]=t;
        chessboard(r1,c1+s,r1+s-1,c1+s,s);
    }
    //downleft
    if(r2>=r1+s&&c2<c1+s)//判断是不是再左下方部分
    {
        chessboard(r1+s,c1,r2,c2,s);
    }
    else
    {
        board[r1+s][c1+s-1]=t;
        chessboard(r1+s,c1,r1+s,c1+s-1,s);
    }
    //downright
    if(r2>=r1+s&&c2>=c1+s)//判断是不是再右下方部分
    {
        chessboard(r1+s,c1+s,r2,c2,s);
    }
    else
    {
        board[r1+s][c1+s]=t;
        chessboard(r1+s,c1+s,r1+s,c1+s,s);
    }
}
void out(int n)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cout<<board[i][j]<<"    ";
        }
        cout<<endl;
    }
}
int main()
{
    int n,u,v;
    while(cin>>n>>u>>v)
    {
        board[u][v]=0;
        time1=0;
        chessboard(1,1,u,v,n);
        out(n);
    }
    return 0;
}


你可能感兴趣的:(棋盘覆盖问题)