用分治策略,设计出解棋盘覆盖问题的方法。
在一个2k *2k的矩阵中,可以分割为4个2k-1 *2k-1子棋盘,如(a)所示,特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,可以用一个L型骨牌覆盖这3个较小棋盘的会合处,如 (b)所示,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种分割,直至棋盘简化为棋盘1×1。
算法如下:
package cn.aaa;
import java.util.Scanner;
public class ChessBoard {
static int tiel=1;
static int size=4;
static int board[][] = new int[size][size];
public static void ChessBoard(int tr,int tc,int dr,int dc,int size) { //tr为棋盘左上角方格的行数,tc为棋盘左上角方格的列数,
//dr为特殊方格的所在的行号,dc为特殊方格所在的列号,size为棋盘的规格
if(size==1) return;
int t = tiel++; //L型骨牌的个数
int s = size/2; //分割棋盘
//覆盖左上角子棋盘
if(dr<tr+s && dc<tc+s){
ChessBoard(tr,tc,dr,dc,s); //特殊方格在此棋盘中
}else{ //此棋盘中无特殊方格
board[tr+s-1][tc+s-1]=t; //用t号L型骨牌覆盖右下角
ChessBoard(tr,tc,tr+s-1,tc+s-1,s); //覆盖其余方格
}
//覆盖右上角子棋盘
if(dr<tr+s && dc>=tc+s){
ChessBoard(tr,tc+s,dr,dc,s); //特殊方格在此棋盘中
}else{ //此棋盘中无特殊方格
board[tr+s-1][tc+s]=t; //用t号L型骨牌覆盖右下角
ChessBoard(tr,tc+s,tr+s-1,tc+s,s); //覆盖其余方格
}
//覆盖左下角子棋盘
if(dr>=tr+s && dc<tc+s){
ChessBoard(tr+s,tc,dr,dc,s); //特殊方格在此棋盘中
}else{ //此棋盘中无特殊方格
board[tr+s][tc+s-1]=t; //用t号L型骨牌覆盖右下角
ChessBoard(tr+s,tc,tr+s,tr+s-1,s); //覆盖其余方格
}
//覆盖右下角子棋盘
if(dr>=tr+s && dc>=tc+s){
ChessBoard(tr+s,tc+s,dr,dc,s);
}else{
board[tr+s][tc+s]=t;
ChessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
public static void main(String[] args) {
ChessBoard(0,0,0,0,size); //特殊方格在左上角
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.print(board[i][j]+" ");
}
System.out.println();
}
}
}
结果显示: