問題描述
在一個2^k×2^k 個方格組成的棋盤中,恰有一個方格與其他方格不同,稱該方格為一特殊方格,且稱該棋盤為一特殊棋盤。在棋盤覆蓋問題中,要用圖示的4種不同形態的L型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重疊覆蓋。
解題思路
分析:當k>0時,將2k×2k棋盤分割為4個2^k-1×2^k-1 子棋盤(a)所示。特殊方格必位於4個較小子棋盤之一中,其余3個子棋盤中無特殊方格。為了將這3個無特殊方格的子棋盤轉化為特殊棋盤,可以用一個L型骨牌覆蓋這3個較小棋盤的會合處,如 (b)所示,從而將原問題轉化為4個較小規模的棋盤覆蓋問題。遞歸地使用這種分割,直至棋盤簡化為棋盤1×1。(出自算法設計與分析-王曉東)
實現:每次都對分割后的四個小方塊進行判斷,判斷特殊方格是否在里面。這里的判斷的方法是每次先記錄下整個大方塊的左上角(top left coner)方格的行列坐標,然后再與特殊方格坐標進行比較,就可以知道特殊方格是否在該塊中。如果特殊方塊在里面,這直接遞歸下去求即可,如果不在,這根據分割的四個方塊的不同位置,把右下角、左下角、右上角或者左上角的方格標記為特殊方塊,然后繼續遞歸。在遞歸函數里,還要有一個變量s來記錄邊的方格數,每次對方塊進行划分時,邊的方格數都會減半,這個變量是為了方便判斷特殊方格的位置。其次還要有一個變nCount來記錄L型骨牌的數量。
代碼實現:
#include <stdio.h> #include <stdlib.h> int nCount = 0; int Matrix[100][100]; void chessBoard(int tr, int tc, int dr, int dc, int size); int main() { int size,r,c,row,col; memset(Matrix,0,sizeof(Matrix)); scanf("%d",&size); scanf("%d%d",&row,&col); chessBoard(0,0,row,col,size); for (r = 0; r < size; r++) { for (c = 0; c < size; c++) { printf("%2d ",Matrix[r][c]); } printf("\n"); } return 0; } void chessBoard(int tr, int tc, int dr, int dc, int size) { //tr and tc represent the top left corner's coordinate of the matrix int s,t; if (1 == size) return; s = size/2; //The number of grid the matrix's edge t = ++ nCount; //locate the special grid on bottom right corner if (dr < tr + s && dc < tc +s) { chessBoard(tr,tc,dr,dc,s); } else { Matrix[tr+s-1][tc+s-1] = t; chessBoard(tr,tc,tr+s-1,tc+s-1,s); } //locate the special grid on bottom left corner if (dr < tr + s && dc >= tc + s ) { chessBoard(tr,tc+s,dr,dc,s); } else { Matrix[tr+s-1][tc+s] = t; chessBoard(tr,tc+s,tr+s-1,tc+s,s); } //locate the special grid on top right corner if (dr >= tr + s && dc < tc + s) { chessBoard(tr+s,tc,dr,dc,s); } else { Matrix[tr+s][tc+s-1] = t; chessBoard(tr+s,tc,tr+s,tc+s-1,s); } //locate the special grid on top left corner if (dr >= tr + s && dc >= tc + s) { chessBoard(tr+s,tc+s,dr,dc,s); } else { Matrix[tr+s][tc+s] = t; chessBoard(tr+s,tc+s,tr+s,tc+s,s); } }
2013/6/14 22:30
程序結果: