棋盘覆盖问题
1. 题目:参见《计算机算法设计与分析》P19
2. 分析:当k>0时,将2k×2k的棋盘分成4个2k-1×2k-1的子棋盘。特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘无特殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,我们可以用一个L型骨牌覆盖这3个较小棋盘的汇合处,这3个子棋盘上被L型骨牌覆盖的方格就成为该棋盘上的特殊方格,从而将问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种分割,知道棋盘转化为1×1的棋盘。
3. 代码:
1 #include <iostream> 2 #include <iomanip> 3 #include <string> 4 #include <cstdio> 5 using namespace std; 6 7 #define N 100 8 9 int board[N][N]; 10 int t; 11 12 void chessboard(int tr,int tc,int dr,int dc,int size) 13 { 14 int m,s; 15 if(size==1) return; 16 m=++t; 17 s=size/2; 18 19 //特殊方格在左上角 20 if(dr<tr+s&&dc<tc+s) 21 chessboard(tr,tc,dr,dc,s); 22 else 23 { 24 //如果特殊方格不在这个区域,就将这个区域在这一次递归的整个 25 //区域最中心的位置设置为特殊方格,即将值置为m 26 board[tr+s-1][tc+s-1]=m; 27 //设置之后这个区域就变成了含有特殊方格的区域,实现了递归 28 chessboard(tr,tc,tr+s-1,tc+s-1,s); 29 } 30 31 //特殊方格在右上角 32 if(dr<tr+s&&dc>=tc+s) 33 chessboard(tr,tc+s,dr,dc,s); 34 else 35 { 36 board[tr+s-1][tc+s]=m; 37 chessboard(tr,tc+s,tr+s-1,tc+s,s); 38 } 39 40 //特殊方格在左下角 41 if(dr>=tr+s&&dc<tc+s) 42 chessboard(tr+s,tc,dr,dc,s); 43 else 44 { 45 board[tr+s][tc+s-1]=m; 46 chessboard(tr+s,tc,tr+s,tc+s-1,s); 47 } 48 49 //特殊方格在右下角 50 if(dr>=tr+s&&dc>=tc+s) 51 chessboard(tr+s,tc+s,dr,dc,s); 52 else 53 { 54 board[tr+s][tc+s]=m; 55 chessboard(tr+s,tc+s,tr+s,tc+s,s); 56 } 57 } 58 59 //输出board中的值 60 void print(int n) 61 { 62 int i,j; 63 for (i=0;i<n;i++) 64 { 65 for (j=0;j<n;j++) 66 cout<<std::left<<setw(4)<<board[i][j]; 67 cout<<endl; 68 } 69 } 70 71 void main() 72 { 73 int tr,tc,dr,dc,size; 74 tr=0; 75 tc=0; 76 cout<<"请输入棋盘的大小:"; 77 cin>>size; 78 cout<<"请输入特殊方块的行号:"; 79 cin>>dr; 80 cout<<"请输入特殊方块的列号:"; 81 cin>>dc; 82 //特殊方格设置为0号 83 board[dr-1][dc-1]=0; 84 chessboard(tr,tc,dr-1,dc-1,size); 85 print(size); 86 }
4. 执行结果: