棋盘覆盖(递归+分治)
问题描述:
在一个2^k×2^k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
分析:将一个大方格分为4部分,那么那一个特殊的小方格必定在起4部分中其中一部分,对于小方格处的那一部分,我们递归这一部分,对于其他部分,我们将四部分交界处的小方格标号,然后将其看作特殊的小方格,对其进行递归。
代码:
#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define mod 10000000007
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
const int maxn = 1000 + 5, inf = 0x3f3f3f3f;
int res[maxn][maxn];
static int t = 0;//标号
void chess(int a,int b,int aa,int bb,int length){
//a,b为棋盘左上角X,Y坐标,aa,bb为特殊点坐标,length为棋盘大小
if(length == 1) return;
int l = length/2;
t++;
int tmp = t;
if(aa < a+l && bb < b+l) chess(a,b,aa,bb,l);//特殊点在左上角
else{
res[a+l-1][b+l-1] = tmp;
chess(a,b,a+l-1,b+l-1,l);
}
if(aa < a+l && bb >= b+l) chess(a,b+l,aa,bb,l);//特殊点在左下角
else{
res[a+l-1][b+l] = tmp;
chess(a,b+l,a+l-1,b+l,l);
}
if(aa >= a+l && bb < b+l) chess(a+l,b,aa,bb,l);//特殊点在右上角
else{
res[a+l][b+l-1] = tmp;
chess(a+l,b,a+l,b+l-1,l);
}
if(aa >= a+l && bb >= b+l) chess(a+l,b+l,aa,bb,l);//特殊点在右下角
else{
res[a+l][b+l] = tmp;
chess(a+l,b+l,a+l,b+l,l);
}
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int a,b,aa,bb,k,d;
while(~scanf("%d%d%d",&k,&aa,&bb)){//输入大小,特殊点坐标
mem(res);
a = b = 1;
chess(a,b,aa,bb,k);
for(int i=1;i<=k;i++){
for(int j=1;j<=k;j++){
printf("%3d",res[i][j]);
}
printf("\n");
}
}
}