棋盘覆盖(递归+分治)

问题描述:

在一个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");
        }
    }
}

 

posted @ 2018-07-22 09:39  dslybyme7  阅读(219)  评论(0编辑  收藏  举报