3、棋盘覆盖
在一个2k×2k (k≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。显然,特殊方格在棋盘中可能出现的位置有4k种,因而有4k种不同的棋盘,左图所示是k=2时16种棋盘中的一个。棋盘覆盖问题要求用右图所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
棋盘覆盖主要应用分治法求解,分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。k>0时,可将2k×2k的棋盘划分为4个2k-1×2k-1的子棋盘,如左图所示。这样划分后,由于原棋盘只有一个特殊方格,所以,这4个子棋盘中只有一个子棋盘包含该特殊方格,其余3个子棋盘中没有特殊方格。为了将这3个没有特殊方格的子棋盘转化为特殊棋盘,以便采用递归方法求解,可以用一个L型骨牌覆盖这3个较小棋盘的会合处,如右图所示,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <iomanip>
using namespace std;
int t=1;
int aa[1000][1000];
void qp(int x1,int y1,int x,int y,int size1)
{
if(size1==1) return ;
int s=size1/2;
int w=t++;
if(x<x1+s&&y<y1+s)
qp(x1,y1,x,y,s);
else {
aa[y1+s-1][x1+s-1]=w;
qp(x1,y1,x1+s-1,y1+s-1,s);
}
if(x>=x1+s&&y<y1+s)
qp(x1+s,y1,x,y,s);
else{
aa[y1+s-1][x1+s]=w;
qp(x1+s,y1,x1+s,y1+s-1,s);
}
if(x<x1+s&&y>=y1+s)
qp(x1,y1+s,x,y,s);
else{
aa[y1+s][x1+s-1]=w;
qp(x1,y1+s,x1+s-1,y1+s,s);
}
if(x>=x1+s&&y>=y1+s)
qp(x1+s,y1+s,x,y,s);
else
{
aa[y1+s][x1+s]=w;
qp(x1+s,y1+s,x1+s,y1+s,s);
}
}
int main()
{
int n;
scanf("%d",&n);
int x,y;
scanf("%d %d",&y,&x);
qp(0,0,x,y,n);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
cout<<setw(4)<<aa[i][j];
cout<<endl;
}
return 0;
}