一:问题描述
在一个2^k * 2^k个方格组成的棋盘中,若恰有一个方格与其它方格不同,则称该方格为一特殊方格,称改棋盘为一特殊棋盘。显然特殊方格在棋盘上出现的位置有4^k种情形。因而对任何k>=0,有4^k种不同的特殊棋盘。下图所示的特殊棋盘为k=2时16个特殊棋盘中的一个。
在棋盘覆盖问题中,要用下图中4中不同形态的L型骨牌覆盖一个给定的特殊棋牌上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。易知,在任何一个2^k * 2^k的棋盘中,用到的L型骨牌个数恰为(4^k-1)/3。
用分治策略,可以设计解棋盘问题的一个简捷的算法。
当k>0时,将2^k * 2^k棋盘分割为4个2^(k-1) * 2^(k-1)子棋盘,如下图所示。
特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,我们可以用一个L型骨牌覆盖这3个较小的棋盘的汇合处,如下图所示,这3个子棋盘上被L型骨牌覆盖的方格就成为该棋盘上的特殊方格,从而将原问题化为4个较小规模的棋盘覆盖问题。递归的使用这种分割,直至棋盘简化为1x1棋盘。
#include<iostream> using namespace std; int board[100][100]; int time1=0; void chessboard(int r1,int c1,int r2,int c2,int size) { if(size==1)return ; int t=++time1; int s=size/2;//记录棋盘的大小 //upleft if(r2<r1+s&&c2<c1+s)//判断是不是再左上方部分 { chessboard(r1,c1,r2,c2,s); } else { board[r1+s-1][c1+s-1]=t; chessboard(r1,c1,r1+s-1,c1+s-1,s); } //upright if(r2<r1+s&&c2>=c1+s)//判断是不是再右上方部分 { chessboard(r1,c1+s,r2,c2,s); } else { board[r1+s-1][c1+s]=t; chessboard(r1,c1+s,r1+s-1,c1+s,s); } //downleft if(r2>=r1+s&&c2<c1+s)//判断是不是再左下方部分 { chessboard(r1+s,c1,r2,c2,s); } else { board[r1+s][c1+s-1]=t; chessboard(r1+s,c1,r1+s,c1+s-1,s); } //downright if(r2>=r1+s&&c2>=c1+s)//判断是不是再右下方部分 { chessboard(r1+s,c1+s,r2,c2,s); } else { board[r1+s][c1+s]=t; chessboard(r1+s,c1+s,r1+s,c1+s,s); } } void out(int n) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cout<<board[i][j]<<" "; } cout<<endl; } } int main() { int n,u,v; while(cin>>n>>u>>v) { board[u][v]=0; time1=0; chessboard(1,1,u,v,n); out(n); } return 0; }