问题
在一个n×n (n = 2k)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。
在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
当初自己听了老师说的好久还是不太懂,自己就慢慢琢磨,下面仅仅代表自己的想法
分治与递归: 将一个大的正方形分成4个小正方形,分别为左上角,右上角,左下角,右下角,继续递归分成仅有一个格子的正方形,这里递归结束条件是正方形格子为1,而不是为1时继续递归下去,在这过程中对格子进行处理,也就是覆盖,如果特殊方格在这正方形中则继续递归,如果不在则将对比参照的正方形的对角(左下角的对角是右上角)进行覆盖,构造特殊方格,如此继续下去。
if条件里判断是否在左/右-上/下角正方形中的方法 : 每次按照将小块的正方形的最左上角方格作为元格子,而if里面的chek特殊方格位置不变,改变元格子的位置到小正方形的元格子进行递归
例如:(x1,y1是题目的特殊格子,x,y是元格子(每个区域的正方形的第一个格子为元格子))
if(x1>=x+s&&y1<y+s)//左下角
{
chek(x+s,y,x1,y1,s);
}
else{
a[x+s][y+s-1]=t;
chek(x+s,y,x+s,y+s-1,s);
}
当比较特殊格子是否在左下角时,以左下角黄色格子中为参照格子,元格子加上S要在黄色范围内,以便确定是否是x+s,或者x+s-1,可以把S看成是一个数如2进行计算理解
而 a数组 是将左下角的红色格子进行覆盖,所以是a[x+s] [y+s-1]
else里面的chek 参数是将黄色正方形的第一个格子作为元格子,将上一行代码覆盖的格子作为特殊格子进行填写,而s照常
如此进行下去
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int a[N][N];
int titl=1;
void chek(int x,int y,int x1,int y1,int s2)
{
if(s2==1)
return;
int s=s2/2;
int t=titl++;
if(x1<x+s&&y1<y+s)//左上角
chek(x,y,x1,y1,s);//如果在此正方形内则继续递归
else{//如果不在此正方形内则覆盖构造一个特殊方格,构造左上角的对角为特殊方格
a[x+s-1][y+s-1]=t;//覆盖构造特殊格子
chek(x,y,x+s-1,y+s-1,s);
}
if(x1>=x+s&&y1<y+s)//左下角
{
chek(x+s,y,x1,y1,s);
}
else{
a[x+s][y+s-1]=t;
chek(x+s,y,x+s,y+s-1,s);
}
if(x1<x+s&&y1>=y+s){//右上角
chek(x,y+s,x1,y1,s);
}else{
a[x+s-1][y+s]=t;
chek(x,y+s,x+s-1,y+s,s);
}
if(x1>=x+s&&y1>=y+s)//右下角
chek(x+s,y+s,x1,y1,s);
else{
a[x+s][y+s]=t;
chek(x+s,y+s,x+s,y+s,s);
}
}
int main(){
int k;
while(cin>>k)
{
int dx,dy;
titl=1;
for(int i=0;i<k;i++){
for(int j=0;j<k;j++){
scanf("%d",&a[i][j]);
if(a[i][j]==-1)
{
dx=i;
dy=j;
}
}
}
chek(0,0,dx,dy,k);
for(int i=0;i<k;i++){
for(int j=0;j<k;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
}
return 0;
}