棋盤覆蓋 分治

2021-08-18 18:05:44 字數 2528 閱讀 6647

問題描述:

在乙個2^k×

2^k (k

≥0)個方格組成的棋盤中,恰有乙個方格與其他方格不同,稱該方格為特殊方格。顯然,特殊方格在棋盤中可能出現的位置有

4^k種,因而有

4^k種不同的棋盤,圖

(a)所示是

k=2時

16種棋盤中的乙個。棋盤覆蓋問題(

chess cover problem

)要求用圖

(b)所示的

4種不同形狀的

l型骨牌覆蓋給定棋盤上除特殊方格以外的所有方格,且任何2個

l型骨牌不得重疊覆蓋。

分治的技巧在於如何劃分棋盤,使劃分後的子棋盤的大小相同,並且每個子棋盤均包含乙個特殊方格,從而將原問題分解為規模較小的棋盤覆蓋問題。k>0時,可將

2^k×

2^k的棋盤劃分為4個

2^(k-1)×2^(

k-1)的子棋盤。這樣劃分後,由於原棋盤只有乙個特殊方格,所以,這

4個子棋盤中只有乙個子棋盤包含該特殊方格,其餘

3個子棋盤中沒有特殊方格。為了將這

3個沒有特殊方格的子棋盤轉化為特殊棋盤,以便採用遞迴方法求解,可以用乙個

l型骨牌覆蓋這

3個較小棋盤的會合處從而將原問題轉化為

4個較小規模的棋盤覆蓋問題。遞迴地使用這種劃分策略,直至將棋盤分割為1×

1的子棋盤。

實現分治演算法如下:

/*tr:棋盤左上角的行號

tc:棋盤左上角的列號

dr:特殊方格所在的行號

dc:特殊方格所在的列號

size= 2^k,棋盤規格*/

void chessboard(int tr,int tc,int dr,int dc,int size)

else

//覆蓋左下角棋盤

if(dr>=tr+s && dc=tr+s && dc>=tc+s)

else

}

程式完整**實現:

#includeusing namespace std;

#define n 1000

int tile=1;

int board[n][n];

void chessboard(int tr,int tc,int dr,int dc,int size)

else

//覆蓋左下角棋盤

if(dr>=tr+s && dc=tr+s && dc>=tc+s)

else

}int main()

{ int size;

cin>>size;

for(int i=0; i>dr>>dc;

chessboard(0,0,dr,dc,size);

for(int i=0; i

除錯案例:

若進一步理解遞迴完整過程,可用如下**實現:

//棋盤覆蓋

#includeusing namespace std;

#define n 1000

int tile=1;

int board[n][n];

/*tr:棋盤左上角的行號

tc:棋盤左上角的列號

dr:特殊方格所在的行號

dc:特殊方格所在的列號

size= 2^k,棋盤規格*/

void chessboard(int tr,int tc,int dr,int dc,int size)

{ if(size==1)

return ;

int t=tile++;//l型骨牌號

int s=size/2;

//覆蓋左上角子棋盤

if(dr=tc+s)

{cout<=tc+s)

{cout

for(int i=0; i>dr>>dc;

chessboard(0,0,dr,dc,size);

for(int i=0; i除錯案例:

分治 棋盤覆蓋

題目描述 在乙個2 k 2 k個方格組成的棋盤中,若恰有乙個方格與其它方格不同,則稱該方格為一特殊方格,稱改棋盤為一特殊棋盤。顯然特殊方格在棋盤上出現的位置有4 k種情形。因而對任何k 0,有4 k種不同的特殊棋盤。下圖所示的特殊棋盤為k 2時16個特殊棋盤中的乙個。在棋盤覆蓋問題中,要用下圖中4中...

棋盤覆蓋 分治

include pch.h include iostream using namespace std 棋盤問題,分治演算法 int q 1024 1024 棋盤陣列,全域性變數 static int tile 1 骨牌編號 tr 棋盤左上角行數,tc 棋盤左上角列數,dr 特殊方格所在行數,dc 特...

分治法,棋盤覆蓋

分治法 棋盤覆蓋問題 問題描述 在乙個2k x 2k 即 2 k x 2 k 個方格組成的棋盤中,恰有乙個方格與其他方格不同,稱該方格為一特殊方格,且稱該棋盤為一特殊棋盤。在棋盤覆蓋問題中,要用4不同形態的l型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個l型骨牌不得重疊覆蓋。思想 將...