问题描述:用图所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
思路:应用分治法
分治的技巧在于如何划分棋盘,使划分后的子棋盘的大小相同,并且每个子棋盘均包含一个特殊方格,从而将原问题分解为规模较小的棋盘覆盖问题。k>0 时,可将2^k×2^k的棋盘划分为4个2^(k-1)×2^(k-1)的子棋盘,如图4.11(a)所示。这样划分后,由于原棋盘只有一个特殊方格,所 以,这4个子棋盘中只有一个子棋盘包含该特殊方格,其余3个子棋盘中没有特殊方格。为了将这3个没有特殊方格的子棋盘转化为特殊棋盘,以便采用递归方法求 解,可以用一个L型骨牌覆盖这3个较小棋盘的会合处,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略, 直至将棋盘分割为1×1的子棋盘。
递归:在一个算法调用另一个算法时,系统需要建立递归调用工作栈,并在运行被调用算法之前先完成3件事:
(1)将所有的实参参数,返回地址等信息传递给被调算法保存。
(2)为被调算法的局部变量分配存储区。
(3)将控制转移到被调函数的入口。
从被调算法返回调用算法之前,系统也要完成三项工作:
(1)保存被调算法的计算结果。
(2)释放被调算法的数据区。
(3)依照被调算法保存的返回地址将控制转移到调用算法。
分治法:将规模为n的问题分成k个规模为n/m的子问题去解
public void FromJava() { int N = 8; int specialRow = 0; int specialCol = 1; ChessBoradProblem boradProblem = new ChessBoradProblem(specialRow, specialCol, N); boradProblem.printBoard(specialRow, specialCol, N); } public class ChessBoradProblem { private int[][] board;//棋盘 private int specialRow;//特殊点的行下标 private int specialCol;//特殊点的列下标 private int size; private int type = 0; public ChessBoradProblem(int specialRow, int specialCol, int size) { super(); this.specialRow = specialRow; this.specialCol = specialCol; this.size = size; board = new int[size][size]; } private void ChessBoard(int specialRow,int specialCol,int leftRow,int leftCol,int size){ if(size == 1){ return; } int subSize = size/2; type = type%4 + 1; int n = type; if (specialRow<leftRow+subSize&&specialCol<leftCol+subSize){ ChessBoard (specialRow,specialCol,leftRow,leftCol,subSize); }else { board[leftRow+subSize-1][leftCol+subSize-1]=n; ChessBoard (leftRow+subSize-1,leftCol+subSize-1,leftRow,leftCol,subSize); } if (specialRow<leftRow+subSize&&specialCol>=leftCol+subSize){ ChessBoard (specialRow,specialCol,leftRow,leftCol+subSize,subSize); }else { board[leftRow+subSize-1][leftCol+subSize]=n; ChessBoard (leftRow+subSize-1,leftCol+subSize,leftRow,leftCol+subSize,subSize); } if (specialRow>=leftRow+subSize&&specialCol<leftCol+subSize){ ChessBoard (specialRow,specialCol,leftRow+subSize,leftCol,subSize); }else { board[leftRow+subSize][leftCol+subSize-1]=n; ChessBoard (leftRow+subSize,leftCol+subSize-1,leftRow+subSize,leftCol,subSize); } if (specialRow>=leftRow+subSize&&specialCol>=leftCol+subSize){ ChessBoard (specialRow,specialCol,leftRow+subSize,leftCol+subSize,subSize); }else { board[leftRow+subSize][leftCol+subSize]=n; ChessBoard (leftRow+subSize,leftCol+subSize,leftRow+subSize,leftCol+subSize,subSize); } } public void printBoard(int specialRow,int specialCol,int size){ ChessBoard(specialRow, specialCol, 0, 0, size); printResult(); } private void printResult() { for(int i = 0;i<size;i++){ for(int j = 0;j<size;j++){ System.out.print(board[i][j]+" "); } System.out.println(); } } }