在一個 2^k * 2^k 個方格組成的棋盤中,若恰有一個方格與其它方格不一樣,則稱該方格爲一特殊方格,稱該棋盤爲一特殊棋盤。顯然特殊方格在棋盤上出現的位置有 4^k 種情形。於是對任何 k>=0 ,有 4^k 種不一樣的特殊棋盤。下圖所示的特殊棋盤爲 k=2 時 16 個特殊棋盤中的一個。ios
在棋盤覆蓋問題中,要用下圖中 4 中不一樣形態的 L 型骨牌覆蓋一個給定的特殊×××上除特殊方格之外的全部方格,且任何 2 個 L 型骨牌不得重疊覆蓋。易知,在任何一個 2^k * 2^k 的棋盤中,用到的 L 型骨牌個數恰爲 (4^k-1)/3 。算法
用分治策略,能夠設計解棋盤問題的一個簡捷的算法。
當 k>0 時,將 2^k * 2^k 棋盤分割爲 4 個 2^(k-1) * 2^(k-1) 子棋盤,以下圖所示。ide
特殊方格必位於 4 個較小子棋盤之一中,其他 3 個子棋盤中無特殊方格。爲了將這 3 個無特殊方格的子棋盤轉化爲特殊棋盤,咱們能夠用一個 L 型骨牌覆蓋這 3 個較小的棋盤的匯合處,以下圖所示,這 3 個子棋盤上被 L 型骨牌覆蓋的方格就成爲該棋盤上的特殊方格,從而將原問題化爲 4 個較小規模的棋盤覆蓋問題。遞歸的使用 這種分割,直至棋盤簡化爲 1x1 棋盤。spa
// 棋盤覆蓋問題 #include<iostream> using namespace std; int Board[16][16]; int tile=0; int ChessBoard(int tr, int tc, int dr, int dc, int size){ if(size == 1) return 0; int t=tile++,s=size/2; // 左上 if(dr<tr+s && dc<tc+s) ChessBoard(tr,tc,dr,dc,s); else{ Board[tr+s-1][tc+s-1]=t; ChessBoard(tr,tc,tr+s-1,tc+s-1,s); } // 右上 if(dr>=tr+s && dc<tc+s) ChessBoard(tr+s,tc,dr,dc,s); else{ Board[tr+s][tc+s-1]=t; ChessBoard(tr+s,tc,tr+s,tc+s-1,s); } // 左下 if(dr<tr+s && dc>=tc+s) ChessBoard(tr,tc+s,dr,dc,s); else{ Board[tr+s-1][tc+s]=t; ChessBoard(tr,tc+s,tr+s-1,tc+s,s); } // 右下 if(dr>=tr+s && dc>=tc+s) ChessBoard(tr+s,tc+s,dr,dc,s); else{ Board[tr+s][tc+s]=t; ChessBoard(tr+s,tc+s,tr+s,tc+s,s); } } int main(){ ChessBoard(0,0,3,2,16); for(int i=0;i<16;i++){ for(int j=0;j<16;j++) cout<<Board[i][j]<<"\t"; cout<<endl; cout<<endl; } }