1. 程式人生 > 實用技巧 >棋盤覆蓋(分治)

棋盤覆蓋(分治)

問題描述

Description

在一個2k× 2k個方格組成的棋盤中,恰有一個方格與其他方格不同,稱該方格為一特殊方格,且稱該棋盤為一特殊棋盤。在棋盤覆蓋問題中,要用圖示的4種不同形態的L型骨牌覆蓋給定的棋盤上除特殊方格以外的所有方格,L型骨牌不能旋轉,且任何兩個L型骨牌不得重疊覆蓋。

棋盤和標記為紅色的特殊方格 4種L型骨牌

Input

第一行是一個T,表示案例數。對於每一個案例,有三個數KXY分別表示在一個2k× 2k的棋盤中,在第X行第Y列有一個特殊方格。1 ≤K≤ 8

1 ≤X,Y≤ 2k

Output

輸出這個被骨牌覆蓋的棋盤,分別用a,b,c,d表示四種骨牌(分別用以下四種字元圖形表示),特殊方格用*號表示。

aa bb c d
a b cc dd

具體輸出見sample Output

Sample Input

2
2 1 2
1 1 1

Sample Output

c*bb
ccdb
cddd
ccdd
*d
dd

問題分析

在以(1,1)為起點的n階的方陣中,若特殊方塊在左上角,

不難發現(n/2,n/2+1),(n/2+1,n/2),(n/2+1,n/2+1)三個格子將會是d組成的三角,

這樣一來將方塊十字分成四份,每個小方塊就相當於都有一個已經覆蓋的方塊(特殊方塊)

那就是遞迴的思想

程式碼實現

#include<iostream>
using namespace std;
char bian[1000][1000];
int x=1;
void chessBord(int li,int lr,int sl,int sr,int siz ){///其中li方正的左上角的行,lr左上角的列,sl特殊塊的行,sr特殊塊的的列
    if(siz==1) return ;
    bool t=false;
    int s=siz/2;
    if(sl>li+s&&sr>lr+s){///特殊方塊在右下角
        bian[li+s][lr+s]='
a'; bian[li+s+1][lr+s]='a'; bian[li+s][lr+s+1]='a'; chessBord(li+s,lr+s,sl,sr,s); } else{///不在此象限 chessBord(li+s,lr+s,li+s+1,lr+s+1,s); } if(sl>li+s&&sr<=lr+s){///特殊方塊在左下角 bian[li+s][lr+s]='b'; bian[li+s][lr+s+1]='b'; bian[li+s+1][lr+s+1]='b'; chessBord(li+s,lr,sl,sr,s); } else{ chessBord(li+s,lr,li+s+1,lr+s,s); } if(sl<=li+s&&sr>lr+s){///特殊方塊在右上角 bian[li+s][lr+s]='c'; bian[li+s+1][lr+s]='c'; bian[li+s+1][lr+s+1]='c'; chessBord(li,lr+s,sl,sr,s); } else{ chessBord(li,lr+s,li+s,lr+s+1,s); } if(sl<=li+s&&sr<=lr+s){///特殊方塊在左上角 bian[li+s][lr+s+1]='d'; bian[li+s+1][lr+s+1]='d'; bian[li+s+1][lr+s]='d'; chessBord(li,lr,sl,sr,s); } else{ chessBord(li,lr,li+s,lr+s,s); } } int power(int a,int b) { int ans = 1; while(b){ if(b&1){ ans*=a; } a*=a; b>>=1; } return ans; } int main() { int t; cin>>t; while(t--){ int k,x,y; cin>>k>>x>>y; int length=0; length = power(2,k); for(int i=1;i<=length;i++){ for(int j=1;j<=length;j++){ bian[i][j]='0'; } } chessBord(0,0,x,y,length); bian[x][y]='*'; for(int i=1;i<=length;i++){ for(int j=1;j<=length;j++){ cout<<bian[i][j]; } cout<<endl; } } return 0; }