演算法07:棋盤覆蓋——分治法Part3
阿新 • • 發佈:2019-01-26
(3)棋盤覆蓋
在一個2k×2k 個方格組成的棋盤中,恰有一個方格與其它方格不同,稱該方格為一特殊方格,且稱該棋盤為一特殊棋盤。在棋盤覆蓋問題中,要用圖示的4種不同形態的L型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重疊覆蓋。
分治法的思想:當k>0時,將2k×2k棋盤分割為4個2k-1×2k-1 子棋盤。特殊方格必位於4個較小子棋盤之一中,其餘3個子棋盤中無特殊方格。為了將這3個無特殊方格的子棋盤轉化為特殊棋盤,可以用一個L型骨牌覆蓋這3個較小棋盤的會合處,從而將原問題轉化為4個較小規模的棋盤覆蓋問題。遞迴地使用這種分割,直至棋盤簡化為棋盤1×1。
具體演算法:
(1)將棋盤分為4部分,檢查特殊方格是否在左上部分
a.在,繼續將左上部分分割;
b.不在,將這部分右下角的格子填充,作為特殊方格,繼續分割;
(2)將左下角、右上角、右下角按同樣的方式處理
(3)遞迴棋盤為1*1時結束
完整演算法
#include <cstdlib> #include <iostream> using namespace std; int board[100][100]; int t0 = 0; void chess_board(int dx, int dy, int tx, int ty, int size ) { if(size == 1) return; int t = ++t0; int s = size/2; //檢查特殊格是否在左上部分 if(tx < dx+s && ty < dy+s) { chess_board(dx, dy, tx, ty, s); } else{//不在右下角填充 board[dx+s-1][dy+s-1] = t; chess_board(dx, dy, dx+s-1, dy+s-1, s); } //檢查特殊格是否在左下部分 if(tx >= dx+s && ty < dy+s) { chess_board(dx+s, dy, tx, ty, s); } else{//不在右上角填充 board[dx+s][dy+s-1] = t; chess_board(dx+s, dy, dx+s, dy+s-1, s); } //檢查特殊格是否在右上部分 if(tx < dx+s && ty >= dy+s) { chess_board(dx, dy+s, tx, ty, s); } else{//不在左下角填充 board[dx+s-1][dy+s] = t; chess_board(dx, dy+s, dx+s-1, dy+s, s); } //檢查特殊格是否在右下部分 if(tx >= dx+s && ty >= dy+s) { chess_board(dx+s, dy+s, tx, ty, s) ; } else{//不在左上角填充 board[dx+s][dy+s] = t; chess_board(dx+s, dy+s, dx+s, dy+s, s); } } int main() { int size, x, y; while(cin>>size>>x>>y){ chess_board(0, 0, x, y, size); for(int i = 0; i < size; i++){ for(int j = 0; j < size; j++){ cout<<board[i][j]<<" "; } cout<<endl; } } system("PAUSE"); return 0; }
執行結果: