问题
如何应用分治法求解棋盘覆盖问题呢?分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。k>0时,可将2^k×2^k的棋盘划分为4个2^(k-1)×2^(k-1)的子棋盘,如图4.11(a)所示。这样划分后,由于原棋盘只有一个特殊方格,所以,这4个子棋盘中只有一个子棋盘包含该特殊方格,其余3个子棋盘中没有特殊方格。为了将这3个没有特殊方格的子棋盘转化为特殊棋盘,以便采用递归方法求解,可以用一个L型骨牌覆盖这3个较小棋盘的会合处,如图4.11(b)所示,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。
1 //棋盘覆盖问题 2 #include<iostream> 3 #include<cstdio> 4 #include<cstdlib> 5 using namespace std; 6 int board[1025][1025]; 7 static int tile = 1; 8 9 void ChessBoard(int tr,int tc,int dr,int dc,int size){ 10 if( size == 1 ) 11 return ; 12 13 int t = tile++; 14 int s = size/2; 15 16 if( dr<tr+s && dc<tc+s ) 17 ChessBoard(tr,tc,dr,dc,s); 18 else{ 19 board[tr+s-1][tc+s-1] = t; 20 ChessBoard(tr,tc,tr+s-1,tc+s-1,s); 21 } 22 23 if( dr<tr+s && dc>=tc+s ) 24 ChessBoard(tr,tc+s,dr,dc,s); 25 else{ 26 board[tr+s-1][tc+s] = t; 27 ChessBoard(tr,tc+s,tr+s-1,tc+s,s); 28 } 29 30 if( dr>=tr+s && tc<tc+s ) 31 ChessBoard(tr+s,tc,dr,dc,s); 32 else{ 33 board[tr+s][tc+s-1] = t; 34 ChessBoard(tr+s,tc,tr+s,tc+s-1,s); 35 } 36 37 if( dr>=tr+s && dc>=tc+s ) 38 ChessBoard(tr+s,tc+s,dr,dc,s); 39 else{ 40 board[tr+s][tc+s] = t; 41 ChessBoard(tr+s,tc+s,tr+s,tc+s,s); 42 } 43 44 } 45 46 int main(){ 47 int k; 48 while( scanf("%d",&k) != EOF ){ 49 int size = 1<<k; 50 int x,y; 51 cin>>x>>y;//特殊方格的位置 52 ChessBoard(0,0,x,y,size); 53 for( int i = 0; i < size; i++ ){ 54 for( int j = 0; j < size; j++ ) 55 printf("%d ",board[i][j]); 56 cout<<endl; 57 } 58 cout<<endl; 59 } 60 return 0; 61 }