在乙個2k×2k個方格組成的棋盤中,恰有乙個方格與其他方格不同,稱該方格為一特殊方格,且稱該棋盤為一特殊棋盤。在棋盤覆蓋問題中,要用圖示的4種不同形態的l型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個l型骨牌不得重疊覆蓋。
易知,覆蓋任意乙個2k×2k的特殊棋盤,用到的骨牌數恰好為(4k-1)/3。
輸入:第一行為k(棋盤的尺寸),第二行為x,y(1<=x,y<=2^k),分別表示特殊方格所在行與列。
輸出:共2^k行,分別表示覆蓋該格的l型的編號(特殊格用0表示)。
例:輸入: 輸出:
由棋盤的尺寸為2^k * 2^k, 我們可以想到將其分割成四個尺寸為2^k-1 * 2^k-1的子棋盤。可是由於含特殊方格的子棋盤與其他子棋盤不同,問題還是沒有解決。
經過思考,我們發現只要將l型如圖放置在棋盤的**,就可以使四個棋盤都變成特殊棋盤。此時問題也變成四個相同的子問題,運用遞迴就可以解決這個問題了。
當k>0時,將2k×2k棋盤分割為4個2k-1×2k-1 子棋盤(a)所示。特殊方格必位於4個較小子棋盤之一中,其餘3個子棋盤中無特殊方格。為了將這3個無特殊方格的子棋盤轉化為特殊棋盤,可以用乙個l型骨牌覆蓋這3個較小棋盤的會合處,如 (b)所示,從而將原問題轉化為4個較小規模的棋盤覆蓋問題。遞迴地使用這種分割,直至棋盤簡化為棋盤1×1。
用分治策略,可以設計出解棋盤覆蓋問題的簡介演算法。
(1)當k>0時,將2的k次冪乘以2的k次冪棋盤分割為4個2的k-1次冪乘以2的k-1次冪子棋盤。
(2)特殊方格必位於4個較小棋盤之一中,其餘3個子棋盤中無特殊方格。
(3)為了將這3個無特殊方格的子棋盤轉化為特殊棋盤,可以用乙個l型骨牌覆蓋這3個較小棋盤的匯合處,這3個子棋盤被l型骨牌覆蓋的方格就成為該棋盤上的特殊方格,從而將原問題轉化為4個較小規模的棋盤覆蓋問題。遞迴地使用這種分割,直至棋盤簡化為1*1棋盤。
下面介紹棋盤覆蓋問題中資料結構的設計:
(1)棋盤:用二維陣列board[size][size]表示乙個棋盤,其中size=2^k.為了在遞迴處理的過程中使用同乙個棋盤,將陣列board設為全域性變數
(2)子棋盤:在棋盤陣列board[size][size]中,由子棋盤左上角的下標tr,tc和棋盤邊長s表示
(3)特殊方格:用board[dr][dc]表示,dr和dc是該特殊方格在棋盤陣列board中的下標
(4)l型骨牌:乙個2^k *2k的棋盤中有乙個特殊方格,所以,用到l型骨牌的個數為(4k-1)/3,將所有l型骨牌從1開始連續編號,用乙個全域性變數t表示。
說明:整形二維陣列board表示棋盤,borad[0][0]使棋盤的左上角方格。
tile是乙個全域性整形變數,用來表示l形骨牌的編號,初始值為0。
tr:棋盤左上角方格的行號;
tc:棋盤左上角方格的列號;
dr:特殊方各所在的行號;
dc:特殊方各所在的列號;
size:size=2k,棋盤規格為2k×2k。
//劃分棋盤
if(dr < tr + s && dc < tc + s)
else
if(dr < tr + s && dc >= tc + s)
else
if(dr >= tr + s && dc < tc + s)
else
if(dr >= tr + s && dc >= tc + s)
else
}t(n)是該演算法覆蓋乙個2k×2k個方格的棋盤的時間,由分支法可得
t(k)= { o(1) k=0,
4t(k- 1)+o(1) k>0 解得遞迴方程t(k)=o(4^k)
覆蓋乙個2k×2k個方格的棋盤所需l型骨牌數為(4^k-1)/3,所以經計算可得該演算法較好。
棋盤覆蓋問題
source code include include include using namespace std const int n 1024 int board n n count void cover int sx,int sy,int cx,int cy,int size,int cx1,i...
棋盤覆蓋問題
問題 在乙個2k 2k k 0 個方格組成的棋盤中,恰有乙個方格與其他方格不同,稱該方格為特殊方格。顯然,特殊方格在棋盤中可能出現的位置有4k種,因而有4k種不同的棋盤,圖4.10 a 所示是k 2時16種棋盤中的乙個。棋盤覆蓋問題 chess cover problem 要求用圖4.10 b 所示...
棋盤覆蓋問題
棋盤覆蓋問題 time limit 1000ms,special time limit 2500ms,memory limit 32768kb total submit users 103,accepted users 40 problem 10432 no special judgement pr...