問題描述
在一個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
程序結果: